Blender  V3.3
pose_backup.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "ED_armature.h"
8 
9 #include <cstring>
10 
11 #include "BLI_listbase.h"
12 
13 #include "MEM_guardedalloc.h"
14 
15 #include "DNA_action_types.h"
16 #include "DNA_armature_types.h"
17 #include "DNA_object_types.h"
18 
19 #include "BKE_action.h"
20 #include "BKE_action.hh"
21 #include "BKE_armature.hh"
22 #include "BKE_idprop.h"
23 
24 using namespace blender::bke;
25 
26 /* simple struct for storing backup info for one pose channel */
29 
30  struct bPoseChannel *pchan; /* Pose channel this backup is for. */
31 
32  struct bPoseChannel olddata; /* Backup of pose channel. */
33  struct IDProperty *oldprops; /* Backup copy (needs freeing) of pose channel's ID properties. */
34 };
35 
36 struct PoseBackup {
38  ListBase /* PoseChannelBackup* */ backups;
39 };
40 
42  const bAction *action,
43  const BoneNameSet &selected_bone_names)
44 {
45  ListBase backups = {nullptr, nullptr};
46  const bool is_bone_selection_relevant = !selected_bone_names.is_empty();
47 
48  BoneNameSet backed_up_bone_names;
49  /* Make a backup of the given pose channel. */
50  auto store_animated_pchans = [&](FCurve * /* unused */, const char *bone_name) {
51  if (backed_up_bone_names.contains(bone_name)) {
52  /* Only backup each bone once. */
53  return;
54  }
55 
56  bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
57  if (pchan == nullptr) {
58  /* FCurve targets non-existent bone. */
59  return;
60  }
61 
62  if (is_bone_selection_relevant && !selected_bone_names.contains(bone_name)) {
63  return;
64  }
65 
66  PoseChannelBackup *chan_bak = static_cast<PoseChannelBackup *>(
67  MEM_callocN(sizeof(*chan_bak), "PoseChannelBackup"));
68  chan_bak->pchan = pchan;
69  memcpy(&chan_bak->olddata, chan_bak->pchan, sizeof(chan_bak->olddata));
70 
71  if (pchan->prop) {
72  chan_bak->oldprops = IDP_CopyProperty(pchan->prop);
73  }
74 
75  BLI_addtail(&backups, chan_bak);
76  backed_up_bone_names.add_new(bone_name);
77  };
78 
79  /* Call `store_animated_pchans()` for each FCurve that targets a bone. */
80  BKE_action_find_fcurves_with_bones(action, store_animated_pchans);
81 
82  /* PoseBackup is constructed late, so that the above loop can use stack variables. */
83  PoseBackup *pose_backup = static_cast<PoseBackup *>(MEM_callocN(sizeof(*pose_backup), __func__));
84  pose_backup->is_bone_selection_relevant = is_bone_selection_relevant;
85  pose_backup->backups = backups;
86  return pose_backup;
87 }
88 
90 {
91  return pose_backup_create(ob, action, BoneNameSet());
92 }
93 
95 {
96  const bArmature *armature = static_cast<const bArmature *>(ob->data);
97  const BoneNameSet selected_bone_names = BKE_armature_find_selected_bone_names(armature);
98  return pose_backup_create(ob, action, selected_bone_names);
99 }
100 
101 bool ED_pose_backup_is_selection_relevant(const struct PoseBackup *pose_backup)
102 {
103  return pose_backup->is_bone_selection_relevant;
104 }
105 
107 {
108  LISTBASE_FOREACH (PoseChannelBackup *, chan_bak, &pbd->backups) {
109  memcpy(chan_bak->pchan, &chan_bak->olddata, sizeof(chan_bak->olddata));
110 
111  if (chan_bak->oldprops) {
112  IDP_SyncGroupValues(chan_bak->pchan->prop, chan_bak->oldprops);
113  }
114 
115  /* TODO: constraints settings aren't restored yet,
116  * even though these could change (though not that likely) */
117  }
118 }
119 
121 {
122  LISTBASE_FOREACH_MUTABLE (PoseChannelBackup *, chan_bak, &pbd->backups) {
123  if (chan_bak->oldprops) {
124  IDP_FreeProperty(chan_bak->oldprops);
125  }
126  BLI_freelinkN(&pbd->backups, chan_bak);
127  }
128  MEM_freeN(pbd);
129 }
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
void IDP_FreeProperty(struct IDProperty *prop)
Definition: idprop.c:1093
void IDP_SyncGroupValues(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL()
struct IDProperty * IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
bool contains(const Key &key) const
Definition: BLI_set.hh:296
bool is_empty() const
Definition: BLI_set.hh:547
void add_new(const Key &key)
Definition: BLI_set.hh:238
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void BKE_action_find_fcurves_with_bones(const bAction *action, FoundFCurveCallback callback)
Definition: action_bones.cc:21
blender::Set< std::string > BoneNameSet
Definition: BKE_armature.hh:27
BoneNameSet BKE_armature_find_selected_bone_names(const bArmature *armature)
SymEdge< T > * prev(const SymEdge< T > *se)
Definition: delaunay_2d.cc:105
static PoseBackup * pose_backup_create(const Object *ob, const bAction *action, const BoneNameSet &selected_bone_names)
Definition: pose_backup.cc:41
void ED_pose_backup_free(PoseBackup *pbd)
Definition: pose_backup.cc:120
PoseBackup * ED_pose_backup_create_all_bones(const Object *ob, const bAction *action)
Definition: pose_backup.cc:89
bool ED_pose_backup_is_selection_relevant(const struct PoseBackup *pose_backup)
Definition: pose_backup.cc:101
PoseBackup * ED_pose_backup_create_selected_bones(const Object *ob, const bAction *action)
Definition: pose_backup.cc:94
void ED_pose_backup_restore(const PoseBackup *pbd)
Definition: pose_backup.cc:106
struct bPose * pose
void * data
bool is_bone_selection_relevant
Definition: pose_backup.cc:37
ListBase backups
Definition: pose_backup.cc:38
struct bPoseChannel * pchan
Definition: pose_backup.cc:30
struct PoseChannelBackup * next
Definition: pose_backup.cc:28
struct IDProperty * oldprops
Definition: pose_backup.cc:33
struct bPoseChannel olddata
Definition: pose_backup.cc:32
IDProperty * prop