Blender  V2.93
pose_utils.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2009, Blender Foundation, Joshua Leung
17  * This is a new part of Blender
18  */
19 
24 #include "MEM_guardedalloc.h"
25 
26 #include "BLI_blenlib.h"
27 #include "BLI_math.h"
28 
29 #include "DNA_anim_types.h"
30 #include "DNA_armature_types.h"
31 #include "DNA_object_types.h"
32 #include "DNA_scene_types.h"
33 
34 #include "BKE_action.h"
35 #include "BKE_anim_data.h"
36 #include "BKE_idprop.h"
37 #include "BKE_layer.h"
38 #include "BKE_object.h"
39 
40 #include "BKE_context.h"
41 
42 #include "DEG_depsgraph.h"
43 
44 #include "RNA_access.h"
45 
46 #include "WM_api.h"
47 #include "WM_types.h"
48 
49 #include "ED_armature.h"
50 #include "ED_keyframing.h"
51 
52 #include "armature_intern.h"
53 
54 /* *********************************************** */
55 /* Contents of this File:
56  *
57  * This file contains methods shared between Pose Slide and Pose Lib;
58  * primarily the functions in question concern Animato <-> Pose
59  * convenience functions, such as applying/getting pose values
60  * and/or inserting keyframes for these.
61  */
62 /* *********************************************** */
63 /* FCurves <-> PoseChannels Links */
64 
65 /* helper for poseAnim_mapping_get() -> get the relevant F-Curves per PoseChannel */
66 static void fcurves_to_pchan_links_get(ListBase *pfLinks,
67  Object *ob,
68  bAction *act,
69  bPoseChannel *pchan)
70 {
71  ListBase curves = {NULL, NULL};
72  int transFlags = action_get_item_transforms(act, ob, pchan, &curves);
73 
74  pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE | POSE_BBONE_SHAPE);
75 
76  /* check if any transforms found... */
77  if (transFlags) {
78  /* make new linkage data */
79  tPChanFCurveLink *pfl = MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink");
81 
82  pfl->ob = ob;
83  pfl->fcurves = curves;
84  pfl->pchan = pchan;
85 
86  /* get the RNA path to this pchan - this needs to be freed! */
87  RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr);
89 
90  /* add linkage data to operator data */
91  BLI_addtail(pfLinks, pfl);
92 
93  /* set pchan's transform flags */
94  if (transFlags & ACT_TRANS_LOC) {
95  pchan->flag |= POSE_LOC;
96  }
97  if (transFlags & ACT_TRANS_ROT) {
98  pchan->flag |= POSE_ROT;
99  }
100  if (transFlags & ACT_TRANS_SCALE) {
101  pchan->flag |= POSE_SIZE;
102  }
103  if (transFlags & ACT_TRANS_BBONE) {
104  pchan->flag |= POSE_BBONE_SHAPE;
105  }
106 
107  /* store current transforms */
108  copy_v3_v3(pfl->oldloc, pchan->loc);
109  copy_v3_v3(pfl->oldrot, pchan->eul);
110  copy_v3_v3(pfl->oldscale, pchan->size);
111  copy_qt_qt(pfl->oldquat, pchan->quat);
112  copy_v3_v3(pfl->oldaxis, pchan->rotAxis);
113  pfl->oldangle = pchan->rotAngle;
114 
115  /* store current bbone values */
116  pfl->roll1 = pchan->roll1;
117  pfl->roll2 = pchan->roll2;
118  pfl->curve_in_x = pchan->curve_in_x;
119  pfl->curve_in_y = pchan->curve_in_y;
120  pfl->curve_out_x = pchan->curve_out_x;
121  pfl->curve_out_y = pchan->curve_out_y;
122  pfl->ease1 = pchan->ease1;
123  pfl->ease2 = pchan->ease2;
124  pfl->scale_in_x = pchan->scale_in_x;
125  pfl->scale_in_y = pchan->scale_in_y;
126  pfl->scale_out_x = pchan->scale_out_x;
127  pfl->scale_out_y = pchan->scale_out_y;
128 
129  /* make copy of custom properties */
130  if (pchan->prop && (transFlags & ACT_TRANS_PROP)) {
131  pfl->oldprops = IDP_CopyProperty(pchan->prop);
132  }
133  }
134 }
135 
140 {
142  if (!ELEM(NULL, ob, ob->data, ob->adt, ob->adt->action)) {
143  return ob;
144  }
145  return NULL;
146 }
147 
148 /* get sets of F-Curves providing transforms for the bones in the Pose */
150 {
151  /* for each Pose-Channel which gets affected, get the F-Curves for that channel
152  * and set the relevant transform flags...
153  */
154  Object *prev_ob, *ob_pose_armature;
155 
156  prev_ob = NULL;
157  ob_pose_armature = NULL;
158  CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob) {
159  if (ob != prev_ob) {
160  prev_ob = ob;
161  ob_pose_armature = poseAnim_object_get(ob);
162  }
163 
164  if (ob_pose_armature == NULL) {
165  continue;
166  }
167 
168  fcurves_to_pchan_links_get(pfLinks, ob_pose_armature, ob_pose_armature->adt->action, pchan);
169  }
170  CTX_DATA_END;
171 
172  /* if no PoseChannels were found, try a second pass, doing visible ones instead
173  * i.e. if nothing selected, do whole pose
174  */
175  if (BLI_listbase_is_empty(pfLinks)) {
176  prev_ob = NULL;
177  ob_pose_armature = NULL;
178  CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) {
179  if (ob != prev_ob) {
180  prev_ob = ob;
181  ob_pose_armature = poseAnim_object_get(ob);
182  }
183 
184  if (ob_pose_armature == NULL) {
185  continue;
186  }
187 
188  fcurves_to_pchan_links_get(pfLinks, ob_pose_armature, ob_pose_armature->adt->action, pchan);
189  }
190  CTX_DATA_END;
191  }
192 }
193 
194 /* free F-Curve <-> PoseChannel links */
196 {
197  tPChanFCurveLink *pfl, *pfln = NULL;
198 
199  /* free the temp pchan links and their data */
200  for (pfl = pfLinks->first; pfl; pfl = pfln) {
201  pfln = pfl->next;
202 
203  /* free custom properties */
204  if (pfl->oldprops) {
206  }
207 
208  /* free list of F-Curve reference links */
209  BLI_freelistN(&pfl->fcurves);
210 
211  /* free pchan RNA Path */
212  MEM_freeN(pfl->pchan_path);
213 
214  /* free link itself */
215  BLI_freelinkN(pfLinks, pfl);
216  }
217 }
218 
219 /* ------------------------- */
220 
221 /* helper for apply() / reset() - refresh the data */
223 {
226 
227  AnimData *adt = BKE_animdata_from_id(&ob->id);
228  if (adt && adt->action) {
230  }
231 }
232 
233 /* reset changes made to current pose */
235 {
236  tPChanFCurveLink *pfl;
237 
238  /* iterate over each pose-channel affected, restoring all channels to their original values */
239  for (pfl = pfLinks->first; pfl; pfl = pfl->next) {
240  bPoseChannel *pchan = pfl->pchan;
241 
242  /* just copy all the values over regardless of whether they changed or not */
243  copy_v3_v3(pchan->loc, pfl->oldloc);
244  copy_v3_v3(pchan->eul, pfl->oldrot);
245  copy_v3_v3(pchan->size, pfl->oldscale);
246  copy_qt_qt(pchan->quat, pfl->oldquat);
247  copy_v3_v3(pchan->rotAxis, pfl->oldaxis);
248  pchan->rotAngle = pfl->oldangle;
249 
250  /* store current bbone values */
251  pchan->roll1 = pfl->roll1;
252  pchan->roll2 = pfl->roll2;
253  pchan->curve_in_x = pfl->curve_in_x;
254  pchan->curve_in_y = pfl->curve_in_y;
255  pchan->curve_out_x = pfl->curve_out_x;
256  pchan->curve_out_y = pfl->curve_out_y;
257  pchan->ease1 = pfl->ease1;
258  pchan->ease2 = pfl->ease2;
259  pchan->scale_in_x = pfl->scale_in_x;
260  pchan->scale_in_y = pfl->scale_in_y;
261  pchan->scale_out_x = pfl->scale_out_x;
262  pchan->scale_out_y = pfl->scale_out_y;
263 
264  /* just overwrite values of properties from the stored copies (there should be some) */
265  if (pfl->oldprops) {
266  IDP_SyncGroupValues(pfl->pchan->prop, pfl->oldprops);
267  }
268  }
269 }
270 
271 /* perform auto-key-framing after changes were made + confirmed */
272 void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks, float cframe)
273 {
274  ViewLayer *view_layer = CTX_data_view_layer(C);
275  View3D *v3d = CTX_wm_view3d(C);
276  bool skip = true;
277 
278  FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
279  ob->id.tag &= ~LIB_TAG_DOIT;
280  ob = poseAnim_object_get(ob);
281 
282  /* Ensure validity of the settings from the context. */
283  if (ob == NULL) {
284  continue;
285  }
286 
287  if (autokeyframe_cfra_can_key(scene, &ob->id)) {
288  ob->id.tag |= LIB_TAG_DOIT;
289  skip = false;
290  }
291  }
293 
294  if (skip) {
295  return;
296  }
297 
298  /* Insert keyframes as necessary if auto-key-framing. */
300  ListBase dsources = {NULL, NULL};
301  tPChanFCurveLink *pfl;
302 
303  /* iterate over each pose-channel affected, tagging bones to be keyed */
304  /* XXX: here we already have the information about what transforms exist, though
305  * it might be easier to just overwrite all using normal mechanisms
306  */
307  for (pfl = pfLinks->first; pfl; pfl = pfl->next) {
308  bPoseChannel *pchan = pfl->pchan;
309 
310  if ((pfl->ob->id.tag & LIB_TAG_DOIT) == 0) {
311  continue;
312  }
313 
314  /* Add data-source override for the PoseChannel, to be used later. */
315  ANIM_relative_keyingset_add_source(&dsources, &pfl->ob->id, &RNA_PoseBone, pchan);
316  }
317 
318  /* insert keyframes for all relevant bones in one go */
319  ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cframe);
320  BLI_freelistN(&dsources);
321 
322  /* do the bone paths
323  * - only do this if keyframes should have been added
324  * - do not calculate unless there are paths already to update...
325  */
326  FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
327  if (ob->id.tag & LIB_TAG_DOIT) {
328  if (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) {
329  // ED_pose_clear_paths(C, ob); /* XXX for now, don't need to clear. */
330  /* TODO(sergey): Should ensure we can use more narrow update range here. */
332  }
333  }
334  }
336 }
337 
338 /* ------------------------- */
339 
340 /* find the next F-Curve for a PoseChannel with matching path...
341  * - path is not just the pfl rna_path, since that path doesn't have property info yet
342  */
343 LinkData *poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, const char *path)
344 {
345  LinkData *first = (prev) ? prev->next : (fcuLinks) ? fcuLinks->first : NULL;
346  LinkData *ld;
347 
348  /* check each link to see if the linked F-Curve has a matching path */
349  for (ld = first; ld; ld = ld->next) {
350  FCurve *fcu = (FCurve *)ld->data;
351 
352  /* check if paths match */
353  if (STREQ(path, fcu->rna_path)) {
354  return ld;
355  }
356  }
357 
358  /* none found */
359  return NULL;
360 }
361 
362 /* *********************************************** */
Blender kernel action and pose functionality.
@ ACT_TRANS_PROP
Definition: BKE_action.h:75
@ ACT_TRANS_SCALE
Definition: BKE_action.h:67
@ ACT_TRANS_BBONE
Definition: BKE_action.h:70
@ ACT_TRANS_ROT
Definition: BKE_action.h:65
@ ACT_TRANS_LOC
Definition: BKE_action.h:63
short action_get_item_transforms(struct bAction *act, struct Object *ob, struct bPoseChannel *pchan, ListBase *curves)
Definition: action.c:1503
struct AnimData * BKE_animdata_from_id(struct ID *id)
Definition: anim_data.c:96
#define CTX_DATA_BEGIN_WITH_ID(C, Type, instance, member, Type_id, instance_id)
Definition: BKE_context.h:266
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:760
#define CTX_DATA_END
Definition: BKE_context.h:260
void IDP_FreeProperty(struct IDProperty *prop)
Definition: idprop.c:1040
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 FOREACH_OBJECT_IN_MODE_END
Definition: BKE_layer.h:284
#define FOREACH_OBJECT_IN_MODE_BEGIN(_view_layer, _v3d, _object_type, _object_mode, _instance)
Definition: BKE_layer.h:280
General operations, lookup, etc. for blender objects.
struct Object * BKE_object_pose_armature_get(struct Object *ob)
Definition: object.c:2487
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:281
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:52
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ ID_RECALC_ANIMATION_NO_FLUSH
Definition: DNA_ID.h:690
@ LIB_TAG_DOIT
Definition: DNA_ID.h:554
@ MOTIONPATH_BAKE_HAS_PATHS
@ POSE_BBONE_SHAPE
@ POSE_ROT
@ POSE_LOC
@ POSE_SIZE
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
@ OB_ARMATURE
@ POSE_PATH_CALC_RANGE_FULL
Definition: ED_armature.h:203
@ MODIFYKEY_MODE_INSERT
#define ANIM_KS_WHOLE_CHARACTER_ID
Read Guarded memory(de)allocation.
StructRNA RNA_PoseBone
#define C
Definition: RandGen.cpp:39
#define ND_POSE
Definition: WM_types.h:359
#define NC_OBJECT
Definition: WM_types.h:280
Scene scene
bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
Definition: keyframing.c:2779
int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
Definition: keyingsets.c:1028
KeyingSet * ANIM_get_keyingset_for_autokeying(const Scene *scene, const char *transformKSName)
Definition: keyingsets.c:725
void ANIM_relative_keyingset_add_source(ListBase *dsources, ID *id, StructRNA *srna, void *data)
Definition: keyingsets.c:898
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob, ePosePathCalcRange range)
Definition: pose_edit.c:203
void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks, float cframe)
Definition: pose_utils.c:272
void poseAnim_mapping_free(ListBase *pfLinks)
Definition: pose_utils.c:195
void poseAnim_mapping_reset(ListBase *pfLinks)
Definition: pose_utils.c:234
LinkData * poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, const char *path)
Definition: pose_utils.c:343
void poseAnim_mapping_get(bContext *C, ListBase *pfLinks)
Definition: pose_utils.c:149
static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *act, bPoseChannel *pchan)
Definition: pose_utils.c:66
void poseAnim_mapping_refresh(bContext *C, Scene *UNUSED(scene), Object *ob)
Definition: pose_utils.c:222
Object * poseAnim_object_get(Object *ob_)
Definition: pose_utils.c:139
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
char * RNA_path_from_ID_to_struct(PointerRNA *ptr)
Definition: rna_access.c:5876
bAction * action
char * rna_path
Definition: DNA_ID.h:273
int tag
Definition: DNA_ID.h:292
void * data
Definition: DNA_listBase.h:42
struct LinkData * next
Definition: DNA_listBase.h:41
void * first
Definition: DNA_listBase.h:47
struct AnimData * adt
void * data
IDProperty * prop
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3157