Listing the "Blender Foundation" as copyright holder implied the Blender Foundation holds copyright to files which may include work from many developers. While keeping copyright on headers makes sense for isolated libraries, Blender's own code may be refactored or moved between files in a way that makes the per file copyright holders less meaningful. Copyright references to the "Blender Foundation" have been replaced with "Blender Authors", with the exception of `./extern/` since these this contains libraries which are more isolated, any changed to license headers there can be handled on a case-by-case basis. Some directories in `./intern/` have also been excluded: - `./intern/cycles/` it's own `AUTHORS` file is planned. - `./intern/opensubdiv/`. An "AUTHORS" file has been added, using the chromium projects authors file as a template. Design task: #110784 Ref !110783.
130 lines
4.0 KiB
C++
130 lines
4.0 KiB
C++
/* SPDX-FileCopyrightText: 2015 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \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.hh"
|
|
|
|
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(Object *ob,
|
|
bAction *action,
|
|
AnimationEvalContext *anim_eval_context,
|
|
ActionApplier applier);
|
|
|
|
} // namespace
|
|
|
|
void BKE_pose_apply_action_selected_bones(Object *ob,
|
|
bAction *action,
|
|
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(Object *ob,
|
|
bAction *action,
|
|
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(Object *ob,
|
|
bAction *action,
|
|
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(Object *ob,
|
|
bAction *action,
|
|
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
|