Blender  V3.3
pose_utils.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2009 Blender Foundation, Joshua Leung. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_blenlib.h"
11 #include "BLI_math.h"
12 
13 #include "DNA_anim_types.h"
14 #include "DNA_armature_types.h"
15 #include "DNA_object_types.h"
16 #include "DNA_scene_types.h"
17 
18 #include "BKE_action.h"
19 #include "BKE_anim_data.h"
20 #include "BKE_idprop.h"
21 #include "BKE_layer.h"
22 #include "BKE_object.h"
23 
24 #include "BKE_context.h"
25 
26 #include "DEG_depsgraph.h"
27 
28 #include "RNA_access.h"
29 #include "RNA_path.h"
30 #include "RNA_prototypes.h"
31 
32 #include "WM_api.h"
33 #include "WM_types.h"
34 
35 #include "ED_armature.h"
36 #include "ED_keyframing.h"
37 
38 #include "armature_intern.h"
39 
40 /* *********************************************** */
41 /* Contents of this File:
42  *
43  * This file contains methods shared between Pose Slide and Pose Lib;
44  * primarily the functions in question concern Animato <-> Pose
45  * convenience functions, such as applying/getting pose values
46  * and/or inserting keyframes for these.
47  */
48 /* *********************************************** */
49 /* FCurves <-> PoseChannels Links */
50 
51 /* helper for poseAnim_mapping_get() -> get the relevant F-Curves per PoseChannel */
52 static void fcurves_to_pchan_links_get(ListBase *pfLinks,
53  Object *ob,
54  bAction *act,
55  bPoseChannel *pchan)
56 {
57  ListBase curves = {NULL, NULL};
58  int transFlags = action_get_item_transforms(act, ob, pchan, &curves);
59 
60  pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE | POSE_BBONE_SHAPE);
61 
62  /* check if any transforms found... */
63  if (transFlags) {
64  /* make new linkage data */
65  tPChanFCurveLink *pfl = MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink");
67 
68  pfl->ob = ob;
69  pfl->fcurves = curves;
70  pfl->pchan = pchan;
71 
72  /* get the RNA path to this pchan - this needs to be freed! */
73  RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr);
75 
76  /* add linkage data to operator data */
77  BLI_addtail(pfLinks, pfl);
78 
79  /* set pchan's transform flags */
80  if (transFlags & ACT_TRANS_LOC) {
81  pchan->flag |= POSE_LOC;
82  }
83  if (transFlags & ACT_TRANS_ROT) {
84  pchan->flag |= POSE_ROT;
85  }
86  if (transFlags & ACT_TRANS_SCALE) {
87  pchan->flag |= POSE_SIZE;
88  }
89  if (transFlags & ACT_TRANS_BBONE) {
90  pchan->flag |= POSE_BBONE_SHAPE;
91  }
92 
93  /* store current transforms */
94  copy_v3_v3(pfl->oldloc, pchan->loc);
95  copy_v3_v3(pfl->oldrot, pchan->eul);
96  copy_v3_v3(pfl->oldscale, pchan->size);
97  copy_qt_qt(pfl->oldquat, pchan->quat);
98  copy_v3_v3(pfl->oldaxis, pchan->rotAxis);
99  pfl->oldangle = pchan->rotAngle;
100 
101  /* store current bbone values */
102  pfl->roll1 = pchan->roll1;
103  pfl->roll2 = pchan->roll2;
104  pfl->curve_in_x = pchan->curve_in_x;
105  pfl->curve_in_z = pchan->curve_in_z;
106  pfl->curve_out_x = pchan->curve_out_x;
107  pfl->curve_out_z = pchan->curve_out_z;
108  pfl->ease1 = pchan->ease1;
109  pfl->ease2 = pchan->ease2;
110 
111  copy_v3_v3(pfl->scale_in, pchan->scale_in);
112  copy_v3_v3(pfl->scale_out, pchan->scale_out);
113 
114  /* make copy of custom properties */
115  if (pchan->prop && (transFlags & ACT_TRANS_PROP)) {
116  pfl->oldprops = IDP_CopyProperty(pchan->prop);
117  }
118  }
119 }
120 
122 {
124  if (!ELEM(NULL, ob, ob->data, ob->adt, ob->adt->action)) {
125  return ob;
126  }
127  return NULL;
128 }
129 
131 {
132  /* for each Pose-Channel which gets affected, get the F-Curves for that channel
133  * and set the relevant transform flags...
134  */
135  Object *prev_ob, *ob_pose_armature;
136 
137  prev_ob = NULL;
138  ob_pose_armature = NULL;
139  CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob) {
140  if (ob != prev_ob) {
141  prev_ob = ob;
142  ob_pose_armature = poseAnim_object_get(ob);
143  }
144 
145  if (ob_pose_armature == NULL) {
146  continue;
147  }
148 
149  fcurves_to_pchan_links_get(pfLinks, ob_pose_armature, ob_pose_armature->adt->action, pchan);
150  }
151  CTX_DATA_END;
152 
153  /* if no PoseChannels were found, try a second pass, doing visible ones instead
154  * i.e. if nothing selected, do whole pose
155  */
156  if (BLI_listbase_is_empty(pfLinks)) {
157  prev_ob = NULL;
158  ob_pose_armature = NULL;
159  CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) {
160  if (ob != prev_ob) {
161  prev_ob = ob;
162  ob_pose_armature = poseAnim_object_get(ob);
163  }
164 
165  if (ob_pose_armature == NULL) {
166  continue;
167  }
168 
169  fcurves_to_pchan_links_get(pfLinks, ob_pose_armature, ob_pose_armature->adt->action, pchan);
170  }
171  CTX_DATA_END;
172  }
173 }
174 
176 {
177  tPChanFCurveLink *pfl, *pfln = NULL;
178 
179  /* free the temp pchan links and their data */
180  for (pfl = pfLinks->first; pfl; pfl = pfln) {
181  pfln = pfl->next;
182 
183  /* free custom properties */
184  if (pfl->oldprops) {
186  }
187 
188  /* free list of F-Curve reference links */
189  BLI_freelistN(&pfl->fcurves);
190 
191  /* free pchan RNA Path */
192  MEM_freeN(pfl->pchan_path);
193 
194  /* free link itself */
195  BLI_freelinkN(pfLinks, pfl);
196  }
197 }
198 
199 /* ------------------------- */
200 
202 {
205 
206  AnimData *adt = BKE_animdata_from_id(&ob->id);
207  if (adt && adt->action) {
209  }
210 }
211 
213 {
214  tPChanFCurveLink *pfl;
215 
216  /* iterate over each pose-channel affected, restoring all channels to their original values */
217  for (pfl = pfLinks->first; pfl; pfl = pfl->next) {
218  bPoseChannel *pchan = pfl->pchan;
219 
220  /* just copy all the values over regardless of whether they changed or not */
221  copy_v3_v3(pchan->loc, pfl->oldloc);
222  copy_v3_v3(pchan->eul, pfl->oldrot);
223  copy_v3_v3(pchan->size, pfl->oldscale);
224  copy_qt_qt(pchan->quat, pfl->oldquat);
225  copy_v3_v3(pchan->rotAxis, pfl->oldaxis);
226  pchan->rotAngle = pfl->oldangle;
227 
228  /* store current bbone values */
229  pchan->roll1 = pfl->roll1;
230  pchan->roll2 = pfl->roll2;
231  pchan->curve_in_x = pfl->curve_in_x;
232  pchan->curve_in_z = pfl->curve_in_z;
233  pchan->curve_out_x = pfl->curve_out_x;
234  pchan->curve_out_z = pfl->curve_out_z;
235  pchan->ease1 = pfl->ease1;
236  pchan->ease2 = pfl->ease2;
237 
238  copy_v3_v3(pchan->scale_in, pfl->scale_in);
239  copy_v3_v3(pchan->scale_out, pfl->scale_out);
240 
241  /* just overwrite values of properties from the stored copies (there should be some) */
242  if (pfl->oldprops) {
243  IDP_SyncGroupValues(pfl->pchan->prop, pfl->oldprops);
244  }
245  }
246 }
247 
248 void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks, float cframe)
249 {
250  ViewLayer *view_layer = CTX_data_view_layer(C);
251  View3D *v3d = CTX_wm_view3d(C);
252  bool skip = true;
253 
254  FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
255  ob->id.tag &= ~LIB_TAG_DOIT;
256  ob = poseAnim_object_get(ob);
257 
258  /* Ensure validity of the settings from the context. */
259  if (ob == NULL) {
260  continue;
261  }
262 
263  if (autokeyframe_cfra_can_key(scene, &ob->id)) {
264  ob->id.tag |= LIB_TAG_DOIT;
265  skip = false;
266  }
267  }
269 
270  if (skip) {
271  return;
272  }
273 
274  /* Insert keyframes as necessary if auto-key-framing. */
276  ListBase dsources = {NULL, NULL};
277  tPChanFCurveLink *pfl;
278 
279  /* iterate over each pose-channel affected, tagging bones to be keyed */
280  /* XXX: here we already have the information about what transforms exist, though
281  * it might be easier to just overwrite all using normal mechanisms
282  */
283  for (pfl = pfLinks->first; pfl; pfl = pfl->next) {
284  bPoseChannel *pchan = pfl->pchan;
285 
286  if ((pfl->ob->id.tag & LIB_TAG_DOIT) == 0) {
287  continue;
288  }
289 
290  /* Add data-source override for the PoseChannel, to be used later. */
291  ANIM_relative_keyingset_add_source(&dsources, &pfl->ob->id, &RNA_PoseBone, pchan);
292  }
293 
294  /* insert keyframes for all relevant bones in one go */
295  ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cframe);
296  BLI_freelistN(&dsources);
297 
298  /* do the bone paths
299  * - only do this if keyframes should have been added
300  * - do not calculate unless there are paths already to update...
301  */
302  FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
303  if (ob->id.tag & LIB_TAG_DOIT) {
304  if (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) {
305  // ED_pose_clear_paths(C, ob); /* XXX for now, don't need to clear. */
306  /* TODO(sergey): Should ensure we can use more narrow update range here. */
308  }
309  }
310  }
312 }
313 
314 /* ------------------------- */
315 
317 {
318  LinkData *first = (prev) ? prev->next : (fcuLinks) ? fcuLinks->first : NULL;
319  LinkData *ld;
320 
321  /* check each link to see if the linked F-Curve has a matching path */
322  for (ld = first; ld; ld = ld->next) {
323  FCurve *fcu = (FCurve *)ld->data;
324 
325  /* check if paths match */
326  if (STREQ(path, fcu->rna_path)) {
327  return ld;
328  }
329  }
330 
331  /* none found */
332  return NULL;
333 }
334 
335 /* *********************************************** */
Blender kernel action and pose functionality.
@ ACT_TRANS_PROP
Definition: BKE_action.h:59
@ ACT_TRANS_SCALE
Definition: BKE_action.h:51
@ ACT_TRANS_BBONE
Definition: BKE_action.h:54
@ ACT_TRANS_ROT
Definition: BKE_action.h:49
@ ACT_TRANS_LOC
Definition: BKE_action.h:47
short action_get_item_transforms(struct bAction *act, struct Object *ob, struct bPoseChannel *pchan, ListBase *curves)
Definition: action.c:1501
struct AnimData * BKE_animdata_from_id(const struct ID *id)
#define CTX_DATA_BEGIN_WITH_ID(C, Type, instance, member, Type_id, instance_id)
Definition: BKE_context.h:284
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
#define CTX_DATA_END
Definition: BKE_context.h:278
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 FOREACH_OBJECT_IN_MODE_END
Definition: BKE_layer.h:384
#define FOREACH_OBJECT_IN_MODE_BEGIN(_view_layer, _v3d, _object_type, _object_mode, _instance)
Definition: BKE_layer.h:380
General operations, lookup, etc. for blender objects.
struct Object * BKE_object_pose_armature_get(struct Object *ob)
Definition: object.cc:2511
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
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:791
@ ID_RECALC_ANIMATION_NO_FLUSH
Definition: DNA_ID.h:879
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
@ 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:297
@ MODIFYKEY_MODE_INSERT
#define ANIM_KS_WHOLE_CHARACTER_ID
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
#define C
Definition: RandGen.cpp:25
#define ND_POSE
Definition: WM_types.h:407
#define NC_OBJECT
Definition: WM_types.h:329
Scene scene
bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
Definition: keyframing.c:2850
int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
Definition: keyingsets.c:1038
KeyingSet * ANIM_get_keyingset_for_autokeying(const Scene *scene, const char *transformKSName)
Definition: keyingsets.c:696
void ANIM_relative_keyingset_add_source(ListBase *dsources, ID *id, StructRNA *srna, void *data)
Definition: keyingsets.c:924
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
SymEdge< T > * prev(const SymEdge< T > *se)
Definition: delaunay_2d.cc:105
void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob, ePosePathCalcRange range)
Definition: pose_edit.c:154
void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks, float cframe)
Definition: pose_utils.c:248
void poseAnim_mapping_free(ListBase *pfLinks)
Definition: pose_utils.c:175
void poseAnim_mapping_reset(ListBase *pfLinks)
Definition: pose_utils.c:212
LinkData * poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, const char *path)
Definition: pose_utils.c:316
void poseAnim_mapping_get(bContext *C, ListBase *pfLinks)
Definition: pose_utils.c:130
static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *act, bPoseChannel *pchan)
Definition: pose_utils.c:52
void poseAnim_mapping_refresh(bContext *C, Scene *UNUSED(scene), Object *ob)
Definition: pose_utils.c:201
Object * poseAnim_object_get(Object *ob_)
Definition: pose_utils.c:121
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
char * RNA_path_from_ID_to_struct(const PointerRNA *ptr)
Definition: rna_path.cc:981
bAction * action
char * rna_path
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
void * data
Definition: DNA_listBase.h:26
struct LinkData * next
Definition: DNA_listBase.h:25
void * first
Definition: DNA_listBase.h:31
struct AnimData * adt
void * data
IDProperty * prop
float scale_out[3]
SymEdge< Arith_t > * next
Definition: delaunay_2d.cc:83
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3480