Merge branch 'master' into blender2.8
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 4 Apr 2018 09:49:24 +0000 (11:49 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 4 Apr 2018 09:49:24 +0000 (11:49 +0200)
1  2 
source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc

index 6a7f9eaea256ede2852399c2749da3ae49541f6b,4e1de16235c3d63a5f226a0c157de1f1f271e8e5..8a2cab2d0fbdadba13ddaebdea683772b32130e9
@@@ -46,7 -46,6 +46,7 @@@ extern "C" 
  #include "DNA_armature_types.h"
  #include "DNA_constraint_types.h"
  #include "DNA_object_types.h"
 +#include "DNA_scene_types.h"
  
  #include "BKE_action.h"
  #include "BKE_armature.h"
@@@ -56,7 -55,6 +56,7 @@@
  #include "DEG_depsgraph_build.h"
  
  #include "intern/builder/deg_builder.h"
 +#include "intern/eval/deg_eval_copy_on_write.h"
  #include "intern/nodes/deg_node.h"
  #include "intern/nodes/deg_node_component.h"
  #include "intern/nodes/deg_node_operation.h"
@@@ -74,8 -72,8 +74,8 @@@ void DepsgraphNodeBuilder::build_pose_c
        add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
                           function_bind(BKE_pose_constraints_evaluate,
                                         _1,
 -                                       scene_,
 -                                       object,
 +                                       get_cow_datablock(scene_),
 +                                       get_cow_datablock(object),
                                         pchan_index),
                           DEG_OPCODE_BONE_CONSTRAINTS);
  }
@@@ -100,12 -98,13 +100,13 @@@ void DepsgraphNodeBuilder::build_ik_pos
        }
  
        int rootchan_index = BLI_findindex(&object->pose->chanbase, rootchan);
+       BLI_assert(rootchan_index != -1);
        /* Operation node for evaluating/running IK Solver. */
        add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
                           function_bind(BKE_pose_iktree_evaluate,
                                         _1,
 -                                       scene_,
 -                                       object,
 +                                       get_cow_datablock(scene_),
 +                                       get_cow_datablock(object),
                                         rootchan_index),
                           DEG_OPCODE_POSE_IK_SOLVER);
  }
@@@ -121,15 -120,15 +122,16 @@@ void DepsgraphNodeBuilder::build_spline
        bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
  
        /* Operation node for evaluating/running Spline IK Solver.
 -       * Store the "root bone" of this chain in the solver, so it knows where to start.
 +       * Store the "root bone" of this chain in the solver, so it knows where to
 +       * start.
         */
        int rootchan_index = BLI_findindex(&object->pose->chanbase, rootchan);
+       BLI_assert(rootchan_index != -1);
        add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
                           function_bind(BKE_pose_splineik_evaluate,
                                         _1,
 -                                       scene_,
 -                                       object,
 +                                       get_cow_datablock(scene_),
 +                                       get_cow_datablock(object),
                                         rootchan_index),
                           DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
  }
  /* Pose/Armature Bones Graph */
  void DepsgraphNodeBuilder::build_rig(Object *object)
  {
 -      bArmature *arm = (bArmature *)object->data;
 +      bArmature *armature = (bArmature *)object->data;
 +      Scene *scene_cow;
 +      Object *object_cow;
 +      bArmature *armature_cow;
 +      if (DEG_depsgraph_use_copy_on_write()) {
 +              /* NOTE: We need to expand both object and armature, so this way we can
 +               * safely create object level pose.
 +               */
 +              scene_cow = get_cow_datablock(scene_);
 +              object_cow = expand_cow_datablock(object);
 +              armature_cow = expand_cow_datablock(armature);
 +      }
 +      else {
 +              scene_cow = scene_;
 +              object_cow = object;
 +              armature_cow = armature;
 +      }
        OperationDepsNode *op_node;
  
 -      /* animation and/or drivers linking posebones to base-armature used to define them
 +      /* Animation and/or drivers linking posebones to base-armature used to
 +       * define them.
 +       *
         * NOTE: AnimData here is really used to control animated deform properties,
 -       *       which ideally should be able to be unique across different instances.
 -       *       Eventually, we need some type of proxy/isolation mechanism in-between here
 -       *       to ensure that we can use same rig multiple times in same scene...
 +       *       which ideally should be able to be unique across different
 +       *       instances. Eventually, we need some type of proxy/isolation
 +       *       mechanism in-between here to ensure that we can use same rig
 +       *       multiple times in same scene.
         */
 -      if (!built_map_.checkIsBuilt(arm)) {
 -              build_animdata(&arm->id);
 +      if (!built_map_.checkIsBuilt(armature)) {
 +              build_animdata(&armature->id);
                /* Make sure pose is up-to-date with armature updates. */
 -              add_operation_node(&arm->id,
 +              add_operation_node(&armature->id,
                                   DEG_NODE_TYPE_PARAMETERS,
                                   NULL,
                                   DEG_OPCODE_PLACEHOLDER,
        }
  
        /* Rebuild pose if not up to date. */
 -      if (object->pose == NULL || (object->pose->flag & POSE_RECALC)) {
 -              BKE_pose_rebuild_ex(object, arm, false);
 +      if (object_cow->pose == NULL || (object->pose->flag & POSE_RECALC)) {
 +              BKE_pose_rebuild(object_cow, armature_cow);
                /* XXX: Without this animation gets lost in certain circumstances
                 * after loading file. Need to investigate further since it does
                 * not happen with simple scenes..
                 */
 -              if (object->adt) {
 -                      object->adt->recalc |= ADT_RECALC_ANIM;
 +              if (object_cow->adt) {
 +                      object_cow->adt->recalc |= ADT_RECALC_ANIM;
                }
        }
  
        /* speed optimization for animation lookups */
 -      if (object->pose) {
 -              BKE_pose_channels_hash_make(object->pose);
 -              if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
 -                      BKE_pose_update_constraint_flags(object->pose);
 +      if (object_cow->pose != NULL) {
 +              BKE_pose_channels_hash_make(object_cow->pose);
 +              if (object_cow->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
 +                      BKE_pose_update_constraint_flags(object_cow->pose);
                }
        }
  
         * - Used for representing each bone within the rig
         * - Acts to encapsulate the evaluation operations (base matrix + parenting,
         *   and constraint stack) so that they can be easily found.
 -       * - Everything else which depends on bone-results hook up to the component only
 -       *   so that we can redirect those to point at either the the post-IK/
 +       * - Everything else which depends on bone-results hook up to the component
 +       *   only so that we can redirect those to point at either the the post-IK/
         *   post-constraint/post-matrix steps, as needed.
         */
  
                                     DEG_NODE_TYPE_EVAL_POSE,
                                     function_bind(BKE_pose_eval_init,
                                                   _1,
 -                                                 scene_,
 -                                                 object),
 +                                                 scene_cow,
 +                                                 object_cow),
                                     DEG_OPCODE_POSE_INIT);
        op_node->set_as_entry();
  
                                     DEG_NODE_TYPE_EVAL_POSE,
                                     function_bind(BKE_pose_eval_init_ik,
                                                   _1,
 -                                                 scene_,
 -                                                 object),
 +                                                 scene_cow,
 +                                                 object_cow),
                                     DEG_OPCODE_POSE_INIT_IK);
  
        op_node = add_operation_node(&object->id,
                                     DEG_NODE_TYPE_EVAL_POSE,
                                     function_bind(BKE_pose_eval_flush,
                                                   _1,
 -                                                 scene_,
 -                                                 object),
 +                                                 scene_cow,
 +                                                 object_cow),
                                     DEG_OPCODE_POSE_DONE);
        op_node->set_as_exit();
  
        /* bones */
        int pchan_index = 0;
 -      LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
 +      LISTBASE_FOREACH (bPoseChannel *, pchan, &object_cow->pose->chanbase) {
                /* Node for bone evaluation. */
                op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, NULL,
                                             DEG_OPCODE_BONE_LOCAL);
                op_node->set_as_entry();
  
                add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
 -                                 function_bind(BKE_pose_eval_bone, _1, scene_, object, pchan_index),
 +                                 function_bind(BKE_pose_eval_bone, _1,
 +                                               scene_cow,
 +                                               object_cow,
 +                                               pchan_index),
                                   DEG_OPCODE_BONE_POSE_PARENT);
  
 +              /* NOTE: Dedicated noop for easier relationship construction. */
                add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
 -                                 NULL, /* NOTE: dedicated noop for easier relationship construction */
 +                                 NULL,
                                   DEG_OPCODE_BONE_READY);
  
                op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
                                             function_bind(BKE_pose_bone_done,
                                                           _1,
 -                                                         object,
 +                                                         object_cow,
                                                           pchan_index),
                                             DEG_OPCODE_BONE_DONE);
                op_node->set_as_exit();
                                           DEG_OPCODE_PARAMETERS_EVAL,
                                           pchan->name);
                }
 -              /* Constraints. */
 +              /* Build constraints. */
                if (pchan->constraints.first != NULL) {
                        build_pose_constraints(object, pchan, pchan_index);
                }
                 *
                 * 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...
 +               *   as in ik-tree building
 +               * - Animated chain-lengths are a problem.
                 */
                LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
                        switch (con->type) {
                }
  
                /* Custom shape. */
 +              /* NOTE: Custom shape datablock is already remapped to CoW version. */
                if (pchan->custom != NULL) {
 -                      build_object(NULL, pchan->custom);
 +                      build_object(NULL,
 +                                   get_orig_datablock(pchan->custom),
 +                                   DEG_ID_LINKED_INDIRECTLY);
                }
  
                pchan_index++;
@@@ -326,52 -299,34 +328,52 @@@ void DepsgraphNodeBuilder::build_proxy_
  {
        bArmature *arm = (bArmature *)object->data;
        OperationDepsNode *op_node;
 -
 -      build_animdata(&arm->id);
 -
 +      Object *object_cow;
 +      if (DEG_depsgraph_use_copy_on_write()) {
 +              /* NOTE: We need to expand both object and armature, so this way we can
 +               * safely create object level pose.
 +               */
 +              object_cow = expand_cow_datablock(object);
 +      }
 +      else {
 +              object_cow = object;
 +      }
 +      /* Sanity check. */
        BLI_assert(object->pose != NULL);
 -
 +      /* Animation. */
 +      build_animdata(&arm->id);
        /* speed optimization for animation lookups */
        BKE_pose_channels_hash_make(object->pose);
 -      if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
 -              BKE_pose_update_constraint_flags(object->pose);
 +      if (object_cow->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
 +              BKE_pose_update_constraint_flags(object_cow->pose);
        }
 -
        op_node = add_operation_node(&object->id,
                                     DEG_NODE_TYPE_EVAL_POSE,
 -                                   function_bind(BKE_pose_eval_proxy_copy, _1, object),
 +                                   function_bind(BKE_pose_eval_proxy_copy,
 +                                                 _1,
 +                                                 object_cow),
                                     DEG_OPCODE_POSE_INIT);
        op_node->set_as_entry();
  
 -
        LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
 -              op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
 -                                           NULL, DEG_OPCODE_BONE_LOCAL);
 +              op_node = add_operation_node(&object->id,
 +                                           DEG_NODE_TYPE_BONE,
 +                                           pchan->name,
 +                                           NULL,
 +                                           DEG_OPCODE_BONE_LOCAL);
                op_node->set_as_entry();
 -
 -              add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
 -                                 NULL, DEG_OPCODE_BONE_READY);
 -
 -              op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
 -                                           NULL, DEG_OPCODE_BONE_DONE);
 +              /* Bone is ready for solvers. */
 +              add_operation_node(&object->id,
 +                                 DEG_NODE_TYPE_BONE,
 +                                 pchan->name,
 +                                 NULL,
 +                                 DEG_OPCODE_BONE_READY);
 +              /* Bone is fully evaluated. */
 +              op_node = add_operation_node(&object->id,
 +                                           DEG_NODE_TYPE_BONE,
 +                                           pchan->name,
 +                                           NULL,
 +                                           DEG_OPCODE_BONE_DONE);
                op_node->set_as_exit();
  
                /* Custom properties. */
                                           pchan->name);
                }
        }
 -
 -      op_node = add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE,
 -                                   NULL, DEG_OPCODE_POSE_DONE);
 +      op_node = add_operation_node(&object->id,
 +                                   DEG_NODE_TYPE_EVAL_POSE,
 +                                   NULL,
 +                                   DEG_OPCODE_POSE_DONE);
        op_node->set_as_exit();
  }