Welcome to mirror list, hosted at ThFree Co, Russian Federation.

armature_pose.cc « intern « blenkernel « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 06be986a6b99f7104235b74dd832b48b9c1cedf4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright 2015 Blender Foundation. All rights reserved. */

/** \file
 * \ingroup bke
 */

#include "BKE_action.hh"
#include "BKE_animsys.h"
#include "BKE_armature.hh"

#include "BLI_function_ref.hh"
#include "BLI_set.hh"

#include "DNA_action_types.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_object_types.h"

#include "RNA_access.h"

using namespace blender::bke;

namespace {

using ActionApplier =
    blender::FunctionRef<void(PointerRNA *, bAction *, const AnimationEvalContext *)>;

/* Forward declarations. */
void pose_apply_disable_fcurves_for_unselected_bones(bAction *action,
                                                     const BoneNameSet &selected_bone_names);
void pose_apply_restore_fcurves(bAction *action);

void pose_apply(struct Object *ob,
                struct bAction *action,
                struct AnimationEvalContext *anim_eval_context,
                ActionApplier applier);

}  // namespace

void BKE_pose_apply_action_selected_bones(struct Object *ob,
                                          struct bAction *action,
                                          struct AnimationEvalContext *anim_eval_context)
{
  auto evaluate_and_apply =
      [](PointerRNA *ptr, bAction *act, const AnimationEvalContext *anim_eval_context) {
        animsys_evaluate_action(ptr, act, anim_eval_context, false);
      };

  pose_apply(ob, action, anim_eval_context, evaluate_and_apply);
}

void BKE_pose_apply_action_all_bones(struct Object *ob,
                                     struct bAction *action,
                                     struct AnimationEvalContext *anim_eval_context)
{
  PointerRNA pose_owner_ptr;
  RNA_id_pointer_create(&ob->id, &pose_owner_ptr);
  animsys_evaluate_action(&pose_owner_ptr, action, anim_eval_context, false);
}

void BKE_pose_apply_action_blend(struct Object *ob,
                                 struct bAction *action,
                                 struct AnimationEvalContext *anim_eval_context,
                                 const float blend_factor)
{
  auto evaluate_and_blend = [blend_factor](PointerRNA *ptr,
                                           bAction *act,
                                           const AnimationEvalContext *anim_eval_context) {
    animsys_blend_in_action(ptr, act, anim_eval_context, blend_factor);
  };

  pose_apply(ob, action, anim_eval_context, evaluate_and_blend);
}

namespace {
void pose_apply(struct Object *ob,
                struct bAction *action,
                struct AnimationEvalContext *anim_eval_context,
                ActionApplier applier)
{
  bPose *pose = ob->pose;
  if (pose == nullptr) {
    return;
  }

  const bArmature *armature = (bArmature *)ob->data;
  const BoneNameSet selected_bone_names = BKE_armature_find_selected_bone_names(armature);
  const bool limit_to_selected_bones = !selected_bone_names.is_empty();

  if (limit_to_selected_bones) {
    /* Mute all FCurves that are not associated with selected bones. This separates the concept of
     * bone selection from the FCurve evaluation code. */
    pose_apply_disable_fcurves_for_unselected_bones(action, selected_bone_names);
  }

  /* Apply the Action. */
  PointerRNA pose_owner_ptr;
  RNA_id_pointer_create(&ob->id, &pose_owner_ptr);

  applier(&pose_owner_ptr, action, anim_eval_context);

  if (limit_to_selected_bones) {
    pose_apply_restore_fcurves(action);
  }
}

void pose_apply_restore_fcurves(bAction *action)
{
  /* TODO(Sybren): Restore the FCurve flags, instead of just erasing the 'disabled' flag. */
  LISTBASE_FOREACH (FCurve *, fcu, &action->curves) {
    fcu->flag &= ~FCURVE_DISABLED;
  }
}

void pose_apply_disable_fcurves_for_unselected_bones(bAction *action,
                                                     const BoneNameSet &selected_bone_names)
{
  auto disable_unselected_fcurve = [&](FCurve *fcu, const char *bone_name) {
    const bool is_bone_selected = selected_bone_names.contains(bone_name);
    if (!is_bone_selected) {
      fcu->flag |= FCURVE_DISABLED;
    }
  };
  BKE_action_find_fcurves_with_bones(action, disable_unselected_fcurve);
}

}  // namespace