Blender  V3.3
pose_transform.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include "DNA_anim_types.h"
9 #include "DNA_armature_types.h"
10 #include "DNA_constraint_types.h"
11 #include "DNA_object_types.h"
12 #include "DNA_scene_types.h"
13 
14 #include "MEM_guardedalloc.h"
15 
16 #include "BLI_blenlib.h"
17 #include "BLI_math.h"
18 #include "BLI_string_utils.h"
19 
20 #include "BKE_action.h"
21 #include "BKE_animsys.h"
22 #include "BKE_appdir.h"
23 #include "BKE_armature.h"
24 #include "BKE_blender_copybuffer.h"
25 #include "BKE_context.h"
26 #include "BKE_deform.h"
27 #include "BKE_idprop.h"
28 #include "BKE_layer.h"
29 #include "BKE_main.h"
30 #include "BKE_object.h"
31 #include "BKE_report.h"
32 
33 #include "DEG_depsgraph.h"
34 #include "DEG_depsgraph_query.h"
35 
36 #include "RNA_access.h"
37 #include "RNA_define.h"
38 #include "RNA_prototypes.h"
39 
40 #include "WM_api.h"
41 #include "WM_types.h"
42 
43 #include "ED_armature.h"
44 #include "ED_keyframing.h"
45 #include "ED_screen.h"
46 #include "ED_util.h"
47 
48 #include "UI_interface.h"
49 #include "UI_resources.h"
50 
51 #include "armature_intern.h"
52 
53 /* -------------------------------------------------------------------- */
57 /* helper for apply_armature_pose2bones - fixes parenting of objects
58  * that are bone-parented to armature */
60 {
61  /* Depsgraph has been ensured to be evaluated at the beginning of the operator.
62  *
63  * Must not evaluate depsgraph here yet, since this will ruin object matrix which we want to
64  * preserve after other changes has been done in the operator.
65  *
66  * TODO(sergey): This seems very similar to `ignore_parent_tx()`, which was now ensured to work
67  * quite reliably. Can we de-duplicate the code? Or at least verify we don't need an extra logic
68  * in this function. */
70  Main *bmain = CTX_data_main(C);
71  Object workob, *ob;
72 
73  /* go through all objects in database */
74  for (ob = bmain->objects.first; ob; ob = ob->id.next) {
75  /* if parent is bone in this armature, apply corrections */
76  if ((ob->parent == armob) && (ob->partype == PARBONE)) {
77  /* apply current transform from parent (not yet destroyed),
78  * then calculate new parent inverse matrix
79  */
80  BKE_object_apply_mat4(ob, ob->obmat, false, false);
81 
83  invert_m4_m4(ob->parentinv, workob.obmat);
84  }
85  }
86 }
87 
88 /* Sets the bone head, tail and roll to match the supplied parameters. */
90  const float pose_mat[4][4],
91  const float new_tail[3],
92  float r_new_arm_mat[4][4])
93 {
94  /* Simply copy the head/tail values from pchan over to curbone. */
95  copy_v3_v3(curbone->head, pose_mat[3]);
96  copy_v3_v3(curbone->tail, new_tail);
97 
98  /* Fix roll:
99  * 1. find auto-calculated roll value for this bone now
100  * 2. remove this from the 'visual' y-rotation
101  */
102  {
103  float premat[3][3], pmat[3][3];
104  float delta[3];
105 
106  /* Obtain new auto y-rotation. */
107  sub_v3_v3v3(delta, curbone->tail, curbone->head);
108 
109  copy_m3_m4(pmat, pose_mat);
110  mat3_vec_to_roll(pmat, delta, &curbone->roll);
111 
112  /* Compute new rest pose matrix if requested. */
113  if (r_new_arm_mat) {
114  vec_roll_to_mat3(delta, curbone->roll, premat);
115  copy_m4_m3(r_new_arm_mat, premat);
116  copy_v3_v3(r_new_arm_mat[3], pose_mat[3]);
117  }
118  }
119 }
120 
121 /* Copy properties over from pchan to curbone and reset channels. */
123  bPoseChannel *pchan,
124  const bPoseChannel *pchan_eval)
125 {
126  /* Combine pose and rest values for bendy bone settings,
127  * then clear the pchan values (so we don't get a double-up).
128  */
129  if (pchan->bone->segments > 1) {
130  /* Combine rest/pose values. */
131  curbone->curve_in_x += pchan_eval->curve_in_x;
132  curbone->curve_in_z += pchan_eval->curve_in_z;
133  curbone->curve_out_x += pchan_eval->curve_out_x;
134  curbone->curve_out_z += pchan_eval->curve_out_z;
135  curbone->roll1 += pchan_eval->roll1;
136  curbone->roll2 += pchan_eval->roll2;
137  curbone->ease1 += pchan_eval->ease1;
138  curbone->ease2 += pchan_eval->ease2;
139 
140  mul_v3_v3(curbone->scale_in, pchan_eval->scale_in);
141  mul_v3_v3(curbone->scale_out, pchan_eval->scale_out);
142 
143  /* Reset pose values. */
144  pchan->curve_in_x = pchan->curve_out_x = 0.0f;
145  pchan->curve_in_z = pchan->curve_out_z = 0.0f;
146  pchan->roll1 = pchan->roll2 = 0.0f;
147  pchan->ease1 = pchan->ease2 = 0.0f;
148 
149  copy_v3_fl(pchan->scale_in, 1.0f);
150  copy_v3_fl(pchan->scale_out, 1.0f);
151  }
152 
153  /* Clear transform values for pchan. */
154  zero_v3(pchan->loc);
155  zero_v3(pchan->eul);
156  unit_qt(pchan->quat);
157  unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
158  pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
159 }
160 
161 /* Adjust the current edit position of the bone using the pose space matrix. */
163  bPoseChannel *pchan,
164  const float delta_mat[4][4],
165  float r_new_arm_mat[4][4])
166 {
167  EditBone *curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
168  float delta[3], new_tail[3], premat[3][3], new_pose[4][4];
169 
170  /* Current orientation matrix. */
171  sub_v3_v3v3(delta, curbone->tail, curbone->head);
172  vec_roll_to_mat3(delta, curbone->roll, premat);
173 
174  /* New location and orientation. */
175  mul_m4_m4m3(new_pose, delta_mat, premat);
176  mul_v3_m4v3(new_pose[3], delta_mat, curbone->head);
177  mul_v3_m4v3(new_tail, delta_mat, curbone->tail);
178 
179  applyarmature_set_edit_position(curbone, new_pose, new_tail, r_new_arm_mat);
180 }
181 
182 /* Data about parent position for Apply To Selected mode. */
185 
186  /* New rest position of the bone with scale included. */
187  float new_rest_mat[4][4];
188  /* New arm_mat of the bone == new_rest_mat without scale. */
189  float new_arm_mat[4][4];
191 
192 /* Recursive walk for Apply To Selected mode; pstate NULL unless child of an applied bone. */
194  bPose *pose,
195  bPose *pose_eval,
196  Bone *bone,
197  ListBase *selected,
199 {
200  bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
201  const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(pose_eval, bone->name);
202 
203  if (!pchan || !pchan_eval) {
204  return;
205  }
206 
207  ApplyArmature_ParentState new_pstate = {.bone = bone};
208 
209  if (BLI_findptr(selected, pchan, offsetof(CollectionPointerLink, ptr.data))) {
210  /* SELECTED BONE: Snap to final pose transform minus un-applied parent effects.
211  *
212  * I.e. bone position with accumulated parent effects but no local
213  * transformation will match the original final pose_mat.
214  *
215  * Pose channels are reset as expected.
216  */
217  EditBone *curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
218  BoneParentTransform invparent;
219  float new_tail[3];
220 
221  if (pchan->parent) {
222  BoneParentTransform old_bpt, new_bpt;
223  float offs_bone[4][4];
224 
225  /* Parent effects on the bone transform that have to be removed. */
226  BKE_bone_offset_matrix_get(bone, offs_bone);
228  bone->inherit_scale_mode,
229  offs_bone,
230  bone->parent->arm_mat,
231  pchan_eval->parent->pose_mat,
232  &old_bpt);
233 
234  /* Applied parent effects that have to be kept, if any. */
235  float(*new_parent_pose)[4] = pstate ? pstate->new_rest_mat : bone->parent->arm_mat;
237  bone->inherit_scale_mode,
238  offs_bone,
239  bone->parent->arm_mat,
240  new_parent_pose,
241  &new_bpt);
242 
244  BKE_bone_parent_transform_combine(&new_bpt, &old_bpt, &invparent);
245  }
246  else {
248  }
249 
250  /* Apply change without inherited unapplied parent transformations. */
251  BKE_bone_parent_transform_apply(&invparent, pchan_eval->pose_mat, new_pstate.new_rest_mat);
252 
253  copy_v3_fl3(new_tail, 0.0, bone->length, 0.0);
254  mul_m4_v3(new_pstate.new_rest_mat, new_tail);
255 
257  curbone, new_pstate.new_rest_mat, new_tail, new_pstate.new_arm_mat);
258  applyarmature_transfer_properties(curbone, pchan, pchan_eval);
259 
260  pstate = &new_pstate;
261  }
262  else if (pstate) {
263  /* UNSELECTED CHILD OF SELECTED: Include applied parent effects.
264  *
265  * The inherited transform of applied (selected) bones is baked
266  * into the rest pose so that the final bone position doesn't
267  * change.
268  *
269  * Pose channels are not changed, with the exception of the inherited
270  * applied parent scale being baked into the location pose channel.
271  */
273  float offs_bone[4][4], delta[4][4], old_chan_loc[3];
274 
275  /* Include applied parent effects. */
276  BKE_bone_offset_matrix_get(bone, offs_bone);
278  bone->inherit_scale_mode,
279  offs_bone,
280  pstate->bone->arm_mat,
281  pstate->new_rest_mat,
282  &bpt);
283 
284  unit_m4(new_pstate.new_rest_mat);
285  BKE_bone_parent_transform_apply(&bpt, new_pstate.new_rest_mat, new_pstate.new_rest_mat);
286 
287  /* Bone location channel in pose space relative to bone head. */
288  mul_v3_mat3_m4v3(old_chan_loc, bpt.loc_mat, pchan_eval->loc);
289 
290  /* Apply the change to the rest bone position. */
291  invert_m4_m4(delta, bone->arm_mat);
292  mul_m4_m4m4(delta, new_pstate.new_rest_mat, delta);
293 
294  applyarmature_adjust_edit_position(arm, pchan, delta, new_pstate.new_arm_mat);
295 
296  /* Location pose channel has to be updated, because it is affected
297  * by parent scaling, and the rest pose has no scale by definition. */
298  if (!(bone->flag & BONE_CONNECTED) && !is_zero_v3(old_chan_loc)) {
299  float inv_parent_arm[4][4];
300 
301  /* Compute the channel coordinate space matrices for the new rest state. */
302  invert_m4_m4(inv_parent_arm, pstate->new_arm_mat);
303  mul_m4_m4m4(offs_bone, inv_parent_arm, new_pstate.new_arm_mat);
305  bone->inherit_scale_mode,
306  offs_bone,
307  pstate->new_arm_mat,
308  pstate->new_arm_mat,
309  &bpt);
310 
311  /* Re-apply the location to keep the final effect. */
312  invert_m4(bpt.loc_mat);
313  mul_v3_mat3_m4v3(pchan->loc, bpt.loc_mat, old_chan_loc);
314  }
315 
316  pstate = &new_pstate;
317  }
318 
319  LISTBASE_FOREACH (Bone *, child, &bone->childbase) {
320  applyarmature_process_selected_recursive(arm, pose, pose_eval, child, selected, pstate);
321  }
322 }
323 
324 /* Reset bone constraint so that it is correct after the pose has been applied. */
325 static void applyarmature_reset_bone_constraint(const bConstraint *constraint)
326 {
327  /* TODO(Sybren): This function needs too much knowledge of the internals of specific constraints.
328  * When it is extended with one or two more constraints, move the functionality into a
329  * bConstraintTypeInfo callback function. */
330  switch (constraint->type) {
332  bStretchToConstraint *stretch_to = (bStretchToConstraint *)constraint->data;
333  stretch_to->orglength = 0.0f; /* Force recalculation on next evaluation. */
334  break;
335  }
336  default:
337  /* Most constraints don't need resetting. */
338  break;
339  }
340 }
341 
342 /* Reset bone constraints of the given pose channel so that they are correct after the pose has
343  * been applied. */
345 {
346  LISTBASE_FOREACH (bConstraint *, constraint, &pchan->constraints) {
348  }
349 }
350 
351 /* Reset all (or only selected) bone constraints so that they are correct after the pose has been
352  * applied. */
353 static void applyarmature_reset_constraints(bPose *pose, const bool use_selected)
354 {
355  for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
356  BLI_assert(pchan->bone != NULL);
357  if (use_selected && (pchan->bone->flag & BONE_SELECTED) == 0) {
358  continue;
359  }
361  }
362 }
363 
364 /* set the current pose as the restpose */
366 {
367  Main *bmain = CTX_data_main(C);
370  /* must be active object, not edit-object */
372  const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
374  bPose *pose;
375  bPoseChannel *pchan;
376  ListBase selected_bones;
377 
378  const bool use_selected = RNA_boolean_get(op->ptr, "selected");
379 
380  /* don't check if editmode (should be done by caller) */
381  if (ob->type != OB_ARMATURE) {
382  return OPERATOR_CANCELLED;
383  }
385  BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature");
386  return OPERATOR_CANCELLED;
387  }
388 
389  /* helpful warnings... */
390  /* TODO: add warnings to be careful about actions, applying deforms first, etc. */
391  if (ob->adt && ob->adt->action) {
392  BKE_report(op->reports,
393  RPT_WARNING,
394  "Actions on this armature will be destroyed by this new rest pose as the "
395  "transforms stored are relative to the old rest pose");
396  }
397 
398  /* Find selected bones before switching to edit mode. */
399  if (use_selected) {
400  CTX_data_selected_pose_bones(C, &selected_bones);
401 
402  if (!selected_bones.first) {
403  return OPERATOR_CANCELLED;
404  }
405  }
406 
407  /* Get editbones of active armature to alter */
408  ED_armature_to_edit(arm);
409 
410  /* get pose of active object and move it out of posemode */
411  pose = ob->pose;
412 
413  if (use_selected) {
414  /* The selected only mode requires a recursive walk to handle parent-child relations. */
415  LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
417  arm, pose, ob_eval->pose, bone, &selected_bones, NULL);
418  }
419 
420  BLI_freelistN(&selected_bones);
421  }
422  else {
423  for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
424  const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
425  EditBone *curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
426 
427  applyarmature_set_edit_position(curbone, pchan_eval->pose_mat, pchan_eval->pose_tail, NULL);
428  applyarmature_transfer_properties(curbone, pchan, pchan_eval);
429  }
430  }
431 
432  /* convert editbones back to bones, and then free the edit-data */
433  ED_armature_from_edit(bmain, arm);
435 
436  /* flush positions of posebones */
438 
439  /* fix parenting of objects which are bone-parented */
441 
442  /* For the affected bones, reset specific constraints that are now known to be invalid. */
443  applyarmature_reset_constraints(pose, use_selected);
444 
445  /* NOTE: notifier might evolve. */
448 
449  return OPERATOR_FINISHED;
450 }
451 
453 {
454  uiLayout *layout = op->layout;
456  PointerRNA ptr;
457 
458  RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
459 
460  uiItemR(layout, &ptr, "selected", 0, NULL, ICON_NONE);
461 }
462 
464 {
465  /* identifiers */
466  ot->name = "Apply Pose as Rest Pose";
467  ot->idname = "POSE_OT_armature_apply";
468  ot->description = "Apply the current pose as the new rest pose";
469 
470  /* callbacks */
474 
475  /* flags */
477 
479  "selected",
480  false,
481  "Selected Only",
482  "Only apply the selected bones (with propagation to children)");
483 }
484 
487 /* -------------------------------------------------------------------- */
491 /* set the current pose as the restpose */
493 {
494  ViewLayer *view_layer = CTX_data_view_layer(C);
495  View3D *v3d = CTX_wm_view3d(C);
496 
497  /* Needed to ensure #bPoseChannel.pose_mat are up to date. */
499 
500  FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
501  const bArmature *arm = ob->data;
502 
503  int chanbase_len = BLI_listbase_count(&ob->pose->chanbase);
504  /* Storage for the calculated matrices to prevent reading from modified values.
505  * NOTE: this could be avoided if children were always calculated before parents
506  * however ensuring this is involved and doesn't give any significant advantage. */
507  struct {
508  float matrix[4][4];
509  bool is_set;
510  } *pchan_xform_array = MEM_mallocN(sizeof(*pchan_xform_array) * chanbase_len, __func__);
511  bool changed = false;
512 
513  int i;
514  LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob->pose->chanbase, i) {
515  if (!((pchan->bone->flag & BONE_SELECTED) && PBONE_VISIBLE(arm, pchan->bone))) {
516  pchan_xform_array[i].is_set = false;
517  continue;
518  }
519 
520  /* `chan_mat` already contains the delta transform from rest pose to pose-mode pose
521  * as that is baked into there so that B-Bones will work. Once we've set this as the
522  * new raw-transform components, don't recalculate the poses yet, otherwise IK result will
523  * change, thus changing the result we may be trying to record. */
524 
525  /* NOTE: For some reason `pchan->chan_mat` can't be used here as it gives odd
526  * rotation/offset, see T38251.
527  * Using `pchan->pose_mat` and bringing it back in bone space seems to work as expected!
528  * This matches how visual key-framing works. */
529  BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, pchan_xform_array[i].matrix);
530  pchan_xform_array[i].is_set = true;
531  changed = true;
532  }
533 
534  if (changed) {
535  /* Perform separately to prevent feedback loop. */
536  LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob->pose->chanbase, i) {
537  if (!pchan_xform_array[i].is_set) {
538  continue;
539  }
540  BKE_pchan_apply_mat4(pchan, pchan_xform_array[i].matrix, true);
541  }
542 
544 
545  /* NOTE: notifier might evolve. */
547  }
548 
549  MEM_freeN(pchan_xform_array);
550  }
552 
553  return OPERATOR_FINISHED;
554 }
555 
557 {
558  /* identifiers */
559  ot->name = "Apply Visual Transform to Pose";
560  ot->idname = "POSE_OT_visual_transform_apply";
561  ot->description = "Apply final constrained position of pose bones to their transform";
562 
563  /* callbacks */
566 
567  /* flags */
569 }
570 
573 /* -------------------------------------------------------------------- */
577 /* This function is used to indicate that a bone is selected
578  * and needs to be included in copy buffer (used to be for inserting keys)
579  */
580 static void set_pose_keys(Object *ob)
581 {
582  bArmature *arm = ob->data;
583  bPoseChannel *chan;
584 
585  if (ob->pose) {
586  for (chan = ob->pose->chanbase.first; chan; chan = chan->next) {
587  Bone *bone = chan->bone;
588  if ((bone) && (bone->flag & BONE_SELECTED) && (arm->layer & bone->layer)) {
589  chan->flag |= POSE_KEY;
590  }
591  else {
592  chan->flag &= ~POSE_KEY;
593  }
594  }
595  }
596 }
597 
608  bPoseChannel *chan,
609  const bool selOnly,
610  const bool flip)
611 {
612  char name[MAXBONENAME];
613 
614  /* get the name - if flipping, we must flip this first */
615  if (flip) {
616  BLI_string_flip_side_name(name, chan->name, false, sizeof(name));
617  }
618  else {
619  BLI_strncpy(name, chan->name, sizeof(name));
620  }
621 
622  /* only copy when:
623  * 1) channel exists - poses are not meant to add random channels to anymore
624  * 2) if selection-masking is on, channel is selected -
625  * only selected bones get pasted on, allowing making both sides symmetrical.
626  */
627  bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, name);
628  if (pchan == NULL) {
629  return NULL;
630  }
631  if (selOnly && (pchan->bone->flag & BONE_SELECTED) == 0) {
632  return NULL;
633  }
634 
635  /* only loc rot size
636  * - only copies transform info for the pose
637  */
638  copy_v3_v3(pchan->loc, chan->loc);
639  copy_v3_v3(pchan->size, chan->size);
640  pchan->flag = chan->flag;
641 
642  /* check if rotation modes are compatible (i.e. do they need any conversions) */
643  if (pchan->rotmode == chan->rotmode) {
644  /* copy the type of rotation in use */
645  if (pchan->rotmode > 0) {
646  copy_v3_v3(pchan->eul, chan->eul);
647  }
648  else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
649  copy_v3_v3(pchan->rotAxis, chan->rotAxis);
650  pchan->rotAngle = chan->rotAngle;
651  }
652  else {
653  copy_qt_qt(pchan->quat, chan->quat);
654  }
655  }
656  else if (pchan->rotmode > 0) {
657  /* quat/axis-angle to euler */
658  if (chan->rotmode == ROT_MODE_AXISANGLE) {
659  axis_angle_to_eulO(pchan->eul, pchan->rotmode, chan->rotAxis, chan->rotAngle);
660  }
661  else {
662  quat_to_eulO(pchan->eul, pchan->rotmode, chan->quat);
663  }
664  }
665  else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
666  /* quat/euler to axis angle */
667  if (chan->rotmode > 0) {
668  eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->eul, chan->rotmode);
669  }
670  else {
671  quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->quat);
672  }
673  }
674  else {
675  /* euler/axis-angle to quat */
676  if (chan->rotmode > 0) {
677  eulO_to_quat(pchan->quat, chan->eul, chan->rotmode);
678  }
679  else {
680  axis_angle_to_quat(pchan->quat, chan->rotAxis, pchan->rotAngle);
681  }
682  }
683 
684  /* B-Bone posing options should also be included... */
685  pchan->curve_in_x = chan->curve_in_x;
686  pchan->curve_in_z = chan->curve_in_z;
687  pchan->curve_out_x = chan->curve_out_x;
688  pchan->curve_out_z = chan->curve_out_z;
689 
690  pchan->roll1 = chan->roll1;
691  pchan->roll2 = chan->roll2;
692  pchan->ease1 = chan->ease1;
693  pchan->ease2 = chan->ease2;
694 
695  copy_v3_v3(pchan->scale_in, chan->scale_in);
696  copy_v3_v3(pchan->scale_out, chan->scale_out);
697 
698  /* paste flipped pose? */
699  if (flip) {
700  pchan->loc[0] *= -1;
701 
702  pchan->curve_in_x *= -1;
703  pchan->curve_out_x *= -1;
704  pchan->roll1 *= -1; /* XXX? */
705  pchan->roll2 *= -1; /* XXX? */
706 
707  /* has to be done as eulers... */
708  if (pchan->rotmode > 0) {
709  pchan->eul[1] *= -1;
710  pchan->eul[2] *= -1;
711  }
712  else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
713  float eul[3];
714 
716  eul[1] *= -1;
717  eul[2] *= -1;
719  }
720  else {
721  float eul[3];
722 
723  normalize_qt(pchan->quat);
724  quat_to_eul(eul, pchan->quat);
725  eul[1] *= -1;
726  eul[2] *= -1;
727  eul_to_quat(pchan->quat, eul);
728  }
729  }
730 
731  /* ID properties */
732  if (chan->prop) {
733  if (pchan->prop) {
734  /* if we have existing properties on a bone, just copy over the values of
735  * matching properties (i.e. ones which will have some impact) on to the
736  * target instead of just blinding replacing all [
737  */
738  IDP_SyncGroupValues(pchan->prop, chan->prop);
739  }
740  else {
741  /* no existing properties, so assume that we want copies too? */
742  pchan->prop = IDP_CopyProperty(chan->prop);
743  }
744  }
745 
746  return pchan;
747 }
748 
751 /* -------------------------------------------------------------------- */
756 {
758  char str[FILE_MAX];
759  /* Sanity checking. */
760  if (ELEM(NULL, ob, ob->pose)) {
761  BKE_report(op->reports, RPT_ERROR, "No pose to copy");
762  return OPERATOR_CANCELLED;
763  }
764  /* Sets chan->flag to POSE_KEY if bone selected. */
765  set_pose_keys(ob);
766  /* Construct a local bmain and only put object and its data into it,
767  * o this way we don't expand any other objects into the copy buffer
768  * file.
769  *
770  * TODO(sergey): Find an easier way to tell copy buffer to only store
771  * data we are actually interested in. Maybe pass it a flag to skip
772  * any datablock expansion?
773  */
774  Main *temp_bmain = BKE_main_new();
776 
777  Object ob_copy = *ob;
778  ob_copy.adt = NULL;
779  bArmature arm_copy = *((bArmature *)ob->data);
780  arm_copy.adt = NULL;
781  ob_copy.data = &arm_copy;
782  BLI_addtail(&temp_bmain->objects, &ob_copy);
783  BLI_addtail(&temp_bmain->armatures, &arm_copy);
784  /* begin copy buffer on a temp bmain. */
785  BKE_copybuffer_copy_begin(temp_bmain);
786  /* Store the whole object to the copy buffer because pose can't be
787  * existing on its own.
788  */
789  BKE_copybuffer_copy_tag_ID(&ob_copy.id);
790  BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer_pose.blend");
791  BKE_copybuffer_copy_end(temp_bmain, str, op->reports);
792  /* We clear the lists so no datablocks gets freed,
793  * This is required because objects in temp bmain shares same pointers
794  * as the real ones.
795  */
796  BLI_listbase_clear(&temp_bmain->objects);
797  BLI_listbase_clear(&temp_bmain->armatures);
798  BKE_main_free(temp_bmain);
799  /* We are all done! */
800  BKE_report(op->reports, RPT_INFO, "Copied pose to buffer");
801  return OPERATOR_FINISHED;
802 }
803 
805 {
806  /* identifiers */
807  ot->name = "Copy Pose";
808  ot->idname = "POSE_OT_copy";
809  ot->description = "Copies the current pose of the selected bones to copy/paste buffer";
810 
811  /* api callbacks */
814 
815  /* flag */
817 }
818 
821 /* -------------------------------------------------------------------- */
826 {
829  bPoseChannel *chan;
830  const bool flip = RNA_boolean_get(op->ptr, "flipped");
831  bool selOnly = RNA_boolean_get(op->ptr, "selected_mask");
832 
833  /* Get KeyingSet to use. */
835 
836  /* Sanity checks. */
837  if (ELEM(NULL, ob, ob->pose)) {
838  return OPERATOR_CANCELLED;
839  }
840 
841  /* Read copy buffer .blend file. */
842  char str[FILE_MAX];
843  Main *tmp_bmain = BKE_main_new();
845 
846  BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer_pose.blend");
847  if (!BKE_copybuffer_read(tmp_bmain, str, op->reports, FILTER_ID_OB)) {
848  BKE_report(op->reports, RPT_ERROR, "Copy buffer is empty");
849  BKE_main_free(tmp_bmain);
850  return OPERATOR_CANCELLED;
851  }
852  /* Make sure data from this file is usable for pose paste. */
853  if (BLI_listbase_count_at_most(&tmp_bmain->objects, 2) != 1) {
854  BKE_report(op->reports, RPT_ERROR, "Copy buffer is not from pose mode");
855  BKE_main_free(tmp_bmain);
856  return OPERATOR_CANCELLED;
857  }
858 
859  Object *object_from = tmp_bmain->objects.first;
860  bPose *pose_from = object_from->pose;
861  if (pose_from == NULL) {
862  BKE_report(op->reports, RPT_ERROR, "Copy buffer has no pose");
863  BKE_main_free(tmp_bmain);
864  return OPERATOR_CANCELLED;
865  }
866 
867  /* If selOnly option is enabled, if user hasn't selected any bones,
868  * just go back to default behavior to be more in line with other
869  * pose tools.
870  */
871  if (selOnly) {
872  if (CTX_DATA_COUNT(C, selected_pose_bones) == 0) {
873  selOnly = false;
874  }
875  }
876 
877  /* Safely merge all of the channels in the buffer pose into any
878  * existing pose.
879  */
880  for (chan = pose_from->chanbase.first; chan; chan = chan->next) {
881  if (chan->flag & POSE_KEY) {
882  /* Try to perform paste on this bone. */
883  bPoseChannel *pchan = pose_bone_do_paste(ob, chan, selOnly, flip);
884  if (pchan != NULL) {
885  /* Keyframing tagging for successful paste, */
886  ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
887  }
888  }
889  }
890  BKE_main_free(tmp_bmain);
891 
892  /* Update event for pose and deformation children. */
894 
895  /* Recalculate paths if any of the bones have paths... */
898  }
899 
900  /* Notifiers for updates, */
902 
903  return OPERATOR_FINISHED;
904 }
905 
907 {
908  PropertyRNA *prop;
909 
910  /* identifiers */
911  ot->name = "Paste Pose";
912  ot->idname = "POSE_OT_paste";
913  ot->description = "Paste the stored pose on to the current pose";
914 
915  /* api callbacks */
918 
919  /* flag */
921 
922  /* properties */
923  prop = RNA_def_boolean(ot->srna,
924  "flipped",
925  false,
926  "Flipped on X-Axis",
927  "Paste the stored pose flipped on to current pose");
929 
931  "selected_mask",
932  false,
933  "On Selected Only",
934  "Only paste the stored pose on to selected bones in the current pose");
935 }
936 
939 /* -------------------------------------------------------------------- */
943 /* clear scale of pose-channel */
944 static void pchan_clear_scale(bPoseChannel *pchan)
945 {
946  if ((pchan->protectflag & OB_LOCK_SCALEX) == 0) {
947  pchan->size[0] = 1.0f;
948  }
949  if ((pchan->protectflag & OB_LOCK_SCALEY) == 0) {
950  pchan->size[1] = 1.0f;
951  }
952  if ((pchan->protectflag & OB_LOCK_SCALEZ) == 0) {
953  pchan->size[2] = 1.0f;
954  }
955 
956  pchan->ease1 = 0.0f;
957  pchan->ease2 = 0.0f;
958 
959  copy_v3_fl(pchan->scale_in, 1.0f);
960  copy_v3_fl(pchan->scale_out, 1.0f);
961 }
962 /* Clear the scale. When X-mirror is enabled,
963  * also clear the scale of the mirrored pose channel. */
964 static void pchan_clear_scale_with_mirrored(const bPose *pose, bPoseChannel *pchan)
965 {
966  if (pose->flag & POSE_MIRROR_EDIT) {
967  bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(pose, pchan->name);
968  if (pchan_mirror != NULL) {
969  pchan_clear_scale(pchan_mirror);
970  }
971  }
972  pchan_clear_scale(pchan);
973 }
974 
975 /* clear location of pose-channel */
976 static void pchan_clear_loc(bPoseChannel *pchan)
977 {
978  if ((pchan->protectflag & OB_LOCK_LOCX) == 0) {
979  pchan->loc[0] = 0.0f;
980  }
981  if ((pchan->protectflag & OB_LOCK_LOCY) == 0) {
982  pchan->loc[1] = 0.0f;
983  }
984  if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) {
985  pchan->loc[2] = 0.0f;
986  }
987 }
988 /* Clear the Location. When X-mirror is enabled,
989  * also clear the location of the mirrored pose channel. */
990 static void pchan_clear_loc_with_mirrored(const bPose *pose, bPoseChannel *pchan)
991 {
992  if (pose->flag & POSE_MIRROR_EDIT) {
993  bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(pose, pchan->name);
994  if (pchan_mirror != NULL) {
995  pchan_clear_loc(pchan_mirror);
996  }
997  }
998  pchan_clear_loc(pchan);
999 }
1000 
1001 /* clear rotation of pose-channel */
1002 static void pchan_clear_rot(bPoseChannel *pchan)
1003 {
1005  /* check if convert to eulers for locking... */
1006  if (pchan->protectflag & OB_LOCK_ROT4D) {
1007  /* perform clamping on a component by component basis */
1008  if (pchan->rotmode == ROT_MODE_AXISANGLE) {
1009  if ((pchan->protectflag & OB_LOCK_ROTW) == 0) {
1010  pchan->rotAngle = 0.0f;
1011  }
1012  if ((pchan->protectflag & OB_LOCK_ROTX) == 0) {
1013  pchan->rotAxis[0] = 0.0f;
1014  }
1015  if ((pchan->protectflag & OB_LOCK_ROTY) == 0) {
1016  pchan->rotAxis[1] = 0.0f;
1017  }
1018  if ((pchan->protectflag & OB_LOCK_ROTZ) == 0) {
1019  pchan->rotAxis[2] = 0.0f;
1020  }
1021 
1022  /* check validity of axis - axis should never be 0,0,0
1023  * (if so, then we make it rotate about y). */
1024  if (IS_EQF(pchan->rotAxis[0], pchan->rotAxis[1]) &&
1025  IS_EQF(pchan->rotAxis[1], pchan->rotAxis[2])) {
1026  pchan->rotAxis[1] = 1.0f;
1027  }
1028  }
1029  else if (pchan->rotmode == ROT_MODE_QUAT) {
1030  if ((pchan->protectflag & OB_LOCK_ROTW) == 0) {
1031  pchan->quat[0] = 1.0f;
1032  }
1033  if ((pchan->protectflag & OB_LOCK_ROTX) == 0) {
1034  pchan->quat[1] = 0.0f;
1035  }
1036  if ((pchan->protectflag & OB_LOCK_ROTY) == 0) {
1037  pchan->quat[2] = 0.0f;
1038  }
1039  if ((pchan->protectflag & OB_LOCK_ROTZ) == 0) {
1040  pchan->quat[3] = 0.0f;
1041  }
1042  }
1043  else {
1044  /* the flag may have been set for the other modes, so just ignore the extra flag... */
1045  if ((pchan->protectflag & OB_LOCK_ROTX) == 0) {
1046  pchan->eul[0] = 0.0f;
1047  }
1048  if ((pchan->protectflag & OB_LOCK_ROTY) == 0) {
1049  pchan->eul[1] = 0.0f;
1050  }
1051  if ((pchan->protectflag & OB_LOCK_ROTZ) == 0) {
1052  pchan->eul[2] = 0.0f;
1053  }
1054  }
1055  }
1056  else {
1057  /* perform clamping using euler form (3-components) */
1058  float eul[3], oldeul[3], quat1[4] = {0};
1059  float qlen = 0.0f;
1060 
1061  if (pchan->rotmode == ROT_MODE_QUAT) {
1062  qlen = normalize_qt_qt(quat1, pchan->quat);
1063  quat_to_eul(oldeul, quat1);
1064  }
1065  else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
1066  axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
1067  }
1068  else {
1069  copy_v3_v3(oldeul, pchan->eul);
1070  }
1071 
1072  eul[0] = eul[1] = eul[2] = 0.0f;
1073 
1074  if (pchan->protectflag & OB_LOCK_ROTX) {
1075  eul[0] = oldeul[0];
1076  }
1077  if (pchan->protectflag & OB_LOCK_ROTY) {
1078  eul[1] = oldeul[1];
1079  }
1080  if (pchan->protectflag & OB_LOCK_ROTZ) {
1081  eul[2] = oldeul[2];
1082  }
1083 
1084  if (pchan->rotmode == ROT_MODE_QUAT) {
1085  eul_to_quat(pchan->quat, eul);
1086 
1087  /* restore original quat size */
1088  mul_qt_fl(pchan->quat, qlen);
1089 
1090  /* quaternions flip w sign to accumulate rotations correctly */
1091  if ((quat1[0] < 0.0f && pchan->quat[0] > 0.0f) ||
1092  (quat1[0] > 0.0f && pchan->quat[0] < 0.0f)) {
1093  mul_qt_fl(pchan->quat, -1.0f);
1094  }
1095  }
1096  else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
1097  eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
1098  }
1099  else {
1100  copy_v3_v3(pchan->eul, eul);
1101  }
1102  }
1103  } /* Duplicated in source/blender/editors/object/object_transform.cc */
1104  else {
1105  if (pchan->rotmode == ROT_MODE_QUAT) {
1106  unit_qt(pchan->quat);
1107  }
1108  else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
1109  /* by default, make rotation of 0 radians around y-axis (roll) */
1110  unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
1111  }
1112  else {
1113  zero_v3(pchan->eul);
1114  }
1115  }
1116 
1117  /* Clear also Bendy Bone stuff - Roll is obvious,
1118  * but Curve X/Y stuff is also kindof rotational in nature... */
1119  pchan->roll1 = 0.0f;
1120  pchan->roll2 = 0.0f;
1121 
1122  pchan->curve_in_x = 0.0f;
1123  pchan->curve_in_z = 0.0f;
1124  pchan->curve_out_x = 0.0f;
1125  pchan->curve_out_z = 0.0f;
1126 }
1127 /* Clear the rotation. When X-mirror is enabled,
1128  * also clear the rotation of the mirrored pose channel. */
1129 static void pchan_clear_rot_with_mirrored(const bPose *pose, bPoseChannel *pchan)
1130 {
1131  if (pose->flag & POSE_MIRROR_EDIT) {
1132  bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(pose, pchan->name);
1133  if (pchan_mirror != NULL) {
1134  pchan_clear_rot(pchan_mirror);
1135  }
1136  }
1137  pchan_clear_rot(pchan);
1138 }
1139 
1140 /* clear loc/rot/scale of pose-channel */
1141 static void pchan_clear_transforms(const bPose *pose, bPoseChannel *pchan)
1142 {
1143  pchan_clear_loc_with_mirrored(pose, pchan);
1144  pchan_clear_rot_with_mirrored(pose, pchan);
1145  pchan_clear_scale_with_mirrored(pose, pchan);
1146 }
1147 
1148 /* --------------- */
1149 
1150 /* generic exec for clear-pose operators */
1152  wmOperator *op,
1153  void (*clear_func)(const bPose *, bPoseChannel *),
1154  const char default_ksName[])
1155 {
1158  bool changed_multi = false;
1159 
1160  /* sanity checks */
1161  if (ELEM(NULL, clear_func, default_ksName)) {
1162  BKE_report(op->reports,
1163  RPT_ERROR,
1164  "Programming error: missing clear transform function or keying set name");
1165  return OPERATOR_CANCELLED;
1166  }
1167 
1168  /* only clear relevant transforms for selected bones */
1169  ViewLayer *view_layer = CTX_data_view_layer(C);
1170  View3D *v3d = CTX_wm_view3d(C);
1171  FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob_iter) {
1172  /* XXX: UGLY HACK (for auto-key + clear transforms). */
1173  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
1174  ListBase dsources = {NULL, NULL};
1175  bool changed = false;
1176 
1177  FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan) {
1178  /* run provided clearing function */
1179  clear_func(ob_iter->pose, pchan);
1180  changed = true;
1181 
1182  /* do auto-keyframing as appropriate */
1183  if (autokeyframe_cfra_can_key(scene, &ob_iter->id)) {
1184  /* tag for autokeying later */
1185  ANIM_relative_keyingset_add_source(&dsources, &ob_iter->id, &RNA_PoseBone, pchan);
1186 
1187 #if 1 /* XXX: Ugly Hack - Run clearing function on evaluated copy of pchan */
1188  bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
1189  clear_func(ob_iter->pose, pchan_eval);
1190 #endif
1191  }
1192  }
1194 
1195  if (changed) {
1196  changed_multi = true;
1197 
1198  /* perform autokeying on the bones if needed */
1199  if (!BLI_listbase_is_empty(&dsources)) {
1200  /* get KeyingSet to use */
1201  KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
1202 
1203  /* insert keyframes */
1204  ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)scene->r.cfra);
1205 
1206  /* now recalculate paths */
1207  if (ob_iter->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) {
1209  }
1210 
1211  BLI_freelistN(&dsources);
1212  }
1213 
1214  DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
1215 
1216  /* NOTE: notifier might evolve. */
1218  }
1219  }
1221 
1222  return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1223 }
1224 
1227 /* -------------------------------------------------------------------- */
1232 {
1235 }
1236 
1238 {
1239  /* identifiers */
1240  ot->name = "Clear Pose Scale";
1241  ot->idname = "POSE_OT_scale_clear";
1242  ot->description = "Reset scaling of selected bones to their default values";
1243 
1244  /* api callbacks */
1247 
1248  /* flags */
1250 }
1251 
1254 /* -------------------------------------------------------------------- */
1259 {
1262 }
1263 
1265 {
1266  /* identifiers */
1267  ot->name = "Clear Pose Rotation";
1268  ot->idname = "POSE_OT_rot_clear";
1269  ot->description = "Reset rotations of selected bones to their default values";
1270 
1271  /* api callbacks */
1274 
1275  /* flags */
1277 }
1278 
1281 /* -------------------------------------------------------------------- */
1286 {
1289 }
1290 
1292 {
1293  /* identifiers */
1294  ot->name = "Clear Pose Location";
1295  ot->idname = "POSE_OT_loc_clear";
1296  ot->description = "Reset locations of selected bones to their default values";
1297 
1298  /* api callbacks */
1301 
1302  /* flags */
1304 }
1305 
1308 /* -------------------------------------------------------------------- */
1313 {
1316 }
1317 
1319 {
1320  /* identifiers */
1321  ot->name = "Clear Pose Transforms";
1322  ot->idname = "POSE_OT_transforms_clear";
1323  ot->description =
1324  "Reset location, rotation, and scaling of selected bones to their default values";
1325 
1326  /* api callbacks */
1329 
1330  /* flags */
1332 }
1333 
1336 /* -------------------------------------------------------------------- */
1341 {
1342  ViewLayer *view_layer = CTX_data_view_layer(C);
1343  View3D *v3d = CTX_wm_view3d(C);
1346  const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
1347  depsgraph, (float)scene->r.cfra);
1348  const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
1349 
1350  FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
1351  if ((ob->adt) && (ob->adt->action)) {
1352  /* XXX: this is just like this to avoid contaminating anything else;
1353  * just pose values should change, so this should be fine
1354  */
1355  bPose *dummyPose = NULL;
1356  Object workob = {{NULL}};
1357  bPoseChannel *pchan;
1358 
1359  /* execute animation step for current frame using a dummy copy of the pose */
1360  BKE_pose_copy_data(&dummyPose, ob->pose, 0);
1361 
1362  BLI_strncpy(workob.id.name, "OB<ClearTfmWorkOb>", sizeof(workob.id.name));
1363  workob.type = OB_ARMATURE;
1364  workob.data = ob->data;
1365  workob.adt = ob->adt;
1366  workob.pose = dummyPose;
1367 
1369  &workob.id, workob.adt, &anim_eval_context, ADT_RECALC_ANIM, false);
1370 
1371  /* Copy back values, but on selected bones only. */
1372  for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
1373  pose_bone_do_paste(ob, pchan, only_select, 0);
1374  }
1375 
1376  /* free temp data - free manually as was copied without constraints */
1377  for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
1378  if (pchan->prop) {
1379  IDP_FreeProperty(pchan->prop);
1380  }
1381  }
1382 
1383  /* was copied without constraints */
1384  BLI_freelistN(&dummyPose->chanbase);
1385  MEM_freeN(dummyPose);
1386  }
1387  else {
1388  /* No animation, so just reset to the rest pose. */
1389  BKE_pose_rest(ob->pose, only_select);
1390  }
1391 
1392  /* notifiers and updates */
1395  }
1397 
1398  return OPERATOR_FINISHED;
1399 }
1400 
1402 {
1403  /* identifiers */
1404  ot->name = "Clear User Transforms";
1405  ot->idname = "POSE_OT_user_transforms_clear";
1406  ot->description = "Reset pose bone transforms to keyframed state";
1407 
1408  /* callbacks */
1411 
1412  /* flags */
1414 
1415  /* properties */
1416  RNA_def_boolean(ot->srna, "only_selected", true, "Only Selected", "Only visible/selected bones");
1417 }
1418 
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
void BKE_pose_copy_data(struct bPose **dst, const struct bPose *src, bool copy_constraints)
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
struct bPoseChannel * BKE_pose_channel_get_mirrored(const struct bPose *pose, const char *name)
void BKE_pose_rest(struct bPose *pose, bool selected_bones_only)
Definition: action.c:1631
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, float eval_time)
Definition: anim_sys.c:761
@ ADT_RECALC_ANIM
Definition: BKE_animsys.h:290
void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, const struct AnimationEvalContext *anim_eval_context, eAnimData_Recalc recalc, bool flush_to_original)
const char * BKE_tempdir_base(void)
Definition: appdir.c:1154
struct bArmature * BKE_armature_from_object(struct Object *ob)
Definition: armature.c:342
void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll)
Definition: armature.c:2067
void BKE_pchan_apply_mat4(struct bPoseChannel *pchan, const float mat[4][4], bool use_compat)
Definition: armature.c:1958
void BKE_bone_parent_transform_combine(const struct BoneParentTransform *in1, const struct BoneParentTransform *in2, struct BoneParentTransform *result)
Definition: armature.c:1827
void BKE_armature_mat_pose_to_bone(struct bPoseChannel *pchan, const float inmat[4][4], float outmat[4][4])
Definition: armature.c:1849
#define FOREACH_PCHAN_SELECTED_IN_OBJECT_END
Definition: BKE_armature.h:564
void BKE_bone_parent_transform_invert(struct BoneParentTransform *bpt)
Definition: armature.c:1820
void BKE_bone_offset_matrix_get(const struct Bone *bone, float offs_bone[4][4])
#define PBONE_VISIBLE(arm, bone)
Definition: BKE_armature.h:549
void BKE_bone_parent_transform_clear(struct BoneParentTransform *bpt)
Definition: armature.c:1813
void vec_roll_to_mat3(const float vec[3], float roll, float r_mat[3][3])
Definition: armature.c:2211
void BKE_pose_where_is(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: armature.c:2538
void BKE_bone_parent_transform_calc_from_matrices(int bone_flag, int inherit_scale_mode, const float offs_bone[4][4], const float parent_arm_mat[4][4], const float parent_pose_mat[4][4], struct BoneParentTransform *r_bpt)
Definition: armature.c:1668
#define FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN(_ob, _pchan)
Definition: BKE_armature.h:560
void BKE_bone_parent_transform_apply(const struct BoneParentTransform *bpt, const float inmat[4][4], float outmat[4][4])
Definition: armature.c:1836
bool BKE_copybuffer_copy_end(struct Main *bmain_src, const char *filename, struct ReportList *reports)
bool BKE_copybuffer_read(struct Main *bmain_dst, const char *libname, struct ReportList *reports, uint64_t id_types_mask)
void BKE_copybuffer_copy_begin(struct Main *bmain_src)
void BKE_copybuffer_copy_tag_ID(struct ID *id)
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
#define CTX_DATA_COUNT(C, member)
Definition: BKE_context.h:290
int CTX_data_selected_pose_bones(const bContext *C, ListBase *list)
Definition: context.c:1430
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
support for deformation groups and hooks.
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
struct Main * BKE_main_new(void)
Definition: main.c:32
void BKE_main_free(struct Main *mainvar)
Definition: main.c:40
const char * BKE_main_blendfile_path_from_global(void)
Definition: main.c:562
General operations, lookup, etc. for blender objects.
bool BKE_object_obdata_is_libdata(const struct Object *ob)
struct Object * BKE_object_pose_armature_get(struct Object *ob)
Definition: object.cc:2511
void BKE_object_apply_mat4(struct Object *ob, const float mat[4][4], bool use_compat, bool use_parent)
Definition: object.cc:3575
void BKE_object_workob_calc_parent(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct Object *workob)
Definition: object.cc:3501
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:344
int BLI_listbase_count_at_most(const struct ListBase *listbase, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
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
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findptr(const struct ListBase *listbase, const void *ptr, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1206
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void mul_m4_m4m3(float R[4][4], const float A[4][4], const float B[3][3])
Definition: math_matrix.c:434
void unit_m4(float m[4][4])
Definition: rct.c:1090
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:102
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:800
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
@ EULER_ORDER_DEFAULT
float normalize_qt(float q[4])
void eulO_to_axis_angle(float axis[3], float *angle, const float eul[3], short order)
void mul_qt_fl(float q[4], float f)
void unit_qt(float q[4])
Definition: math_rotation.c:27
void eul_to_quat(float quat[4], const float eul[3])
void quat_to_eul(float eul[3], const float quat[4])
float normalize_qt_qt(float r[4], const float q[4])
void quat_to_eulO(float eul[3], short order, const float quat[4])
void quat_to_axis_angle(float axis[3], float *angle, const float q[4])
void eulO_to_quat(float quat[4], const float eul[3], short order)
void axis_angle_to_eulO(float eul[3], short order, const float axis[3], float angle)
void unit_axis_angle(float axis[3], float *angle)
Definition: math_rotation.c:19
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
MINLINE void mul_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void zero_v3(float r[3])
#define FILE_MAX
void BLI_join_dirfile(char *__restrict dst, size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1531
#define STRNCPY(dst, src)
Definition: BLI_string.h:483
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
size_t BLI_string_flip_side_name(char *r_name, const char *from_name, bool strip_number, size_t name_len)
Definition: string_utils.c:112
#define UNUSED(x)
#define ELEM(...)
#define IS_EQF(a, b)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
#define FILTER_ID_OB
Definition: DNA_ID.h:916
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ MOTIONPATH_BAKE_HAS_PATHS
@ ROT_MODE_QUAT
@ ROT_MODE_AXISANGLE
@ POSE_KEY
@ POSE_MIRROR_EDIT
#define MAXBONENAME
@ BONE_SELECTED
@ BONE_CONNECTED
@ CONSTRAINT_TYPE_STRETCHTO
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
@ OB_ARMATURE
@ OB_LOCK_ROTZ
@ OB_LOCK_ROT4D
@ OB_LOCK_SCALEZ
@ OB_LOCK_ROTX
@ OB_LOCK_SCALEX
@ OB_LOCK_ROTW
@ OB_LOCK_LOCY
@ OB_LOCK_LOCZ
@ OB_LOCK_ROTY
@ OB_LOCK_SCALEY
@ OB_LOCK_LOCX
@ PARBONE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ POSE_PATH_CALC_RANGE_FULL
Definition: ED_armature.h:297
#define ANIM_KS_LOC_ROT_SCALE_ID
@ MODIFYKEY_MODE_INSERT
#define ANIM_KS_LOCATION_ID
#define ANIM_KS_WHOLE_CHARACTER_ID
#define ANIM_KS_SCALING_ID
#define ANIM_KS_ROTATION_ID
bool ED_operator_posemode(struct bContext *C)
Definition: screen_ops.c:530
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
#define C
Definition: RandGen.cpp:25
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_POSE
Definition: WM_types.h:407
#define ND_TRANSFORM
Definition: WM_types.h:405
#define NC_OBJECT
Definition: WM_types.h:329
void ED_armature_edit_free(struct bArmature *arm)
void ED_armature_from_edit(Main *bmain, bArmature *arm)
EditBone * ED_armature_ebone_find_name(const ListBase *edbo, const char *name)
void ED_armature_to_edit(bArmature *arm)
Scene scene
const Depsgraph * depsgraph
#define str(s)
bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
Definition: keyframing.c:2850
bool ED_autokeyframe_pchan(bContext *C, Scene *scene, Object *ob, bPoseChannel *pchan, KeyingSet *ks)
Definition: keyframing.c:3090
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_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob, ePosePathCalcRange range)
Definition: pose_edit.c:154
static void pchan_clear_scale_with_mirrored(const bPose *pose, bPoseChannel *pchan)
static void applyarmature_process_selected_recursive(bArmature *arm, bPose *pose, bPose *pose_eval, Bone *bone, ListBase *selected, ApplyArmature_ParentState *pstate)
void POSE_OT_armature_apply(wmOperatorType *ot)
static void pchan_clear_transforms(const bPose *pose, bPoseChannel *pchan)
void POSE_OT_transforms_clear(wmOperatorType *ot)
static void applyarmature_reset_bone_constraints(const bPoseChannel *pchan)
void POSE_OT_paste(wmOperatorType *ot)
static int pose_copy_exec(bContext *C, wmOperator *op)
static void applyarmature_set_edit_position(EditBone *curbone, const float pose_mat[4][4], const float new_tail[3], float r_new_arm_mat[4][4])
static int pose_paste_exec(bContext *C, wmOperator *op)
static void pchan_clear_scale(bPoseChannel *pchan)
void POSE_OT_visual_transform_apply(wmOperatorType *ot)
static void applyarmature_fix_boneparents(const bContext *C, Scene *scene, Object *armob)
static void applyarmature_reset_bone_constraint(const bConstraint *constraint)
static void pchan_clear_loc_with_mirrored(const bPose *pose, bPoseChannel *pchan)
static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
static int pose_clear_rot_exec(bContext *C, wmOperator *op)
static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
static int pose_clear_loc_exec(bContext *C, wmOperator *op)
static void applyarmature_reset_constraints(bPose *pose, const bool use_selected)
static void pchan_clear_rot(bPoseChannel *pchan)
static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
void POSE_OT_copy(wmOperatorType *ot)
void POSE_OT_rot_clear(wmOperatorType *ot)
static int pose_clear_scale_exec(bContext *C, wmOperator *op)
static void applyarmature_adjust_edit_position(bArmature *arm, bPoseChannel *pchan, const float delta_mat[4][4], float r_new_arm_mat[4][4])
static void applyarmature_transfer_properties(EditBone *curbone, bPoseChannel *pchan, const bPoseChannel *pchan_eval)
static void apply_armature_pose2bones_ui(bContext *C, wmOperator *op)
void POSE_OT_loc_clear(wmOperatorType *ot)
static void set_pose_keys(Object *ob)
struct ApplyArmature_ParentState ApplyArmature_ParentState
static void pchan_clear_loc(bPoseChannel *pchan)
void POSE_OT_scale_clear(wmOperatorType *ot)
static bPoseChannel * pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bool selOnly, const bool flip)
void POSE_OT_user_transforms_clear(wmOperatorType *ot)
static int pose_clear_transforms_exec(bContext *C, wmOperator *op)
static void pchan_clear_rot_with_mirrored(const bPose *pose, bPoseChannel *pchan)
static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op, void(*clear_func)(const bPose *, bPoseChannel *), const char default_ksName[])
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
bAction * action
float loc_mat[4][4]
Definition: BKE_armature.h:396
struct Bone * parent
char name[64]
char inherit_scale_mode
short segments
float length
float arm_mat[4][4]
ListBase childbase
float curve_out_z
Definition: BKE_armature.h:74
float scale_in[3]
Definition: BKE_armature.h:76
float ease2
Definition: BKE_armature.h:75
float roll1
Definition: BKE_armature.h:72
float tail[3]
Definition: BKE_armature.h:54
float roll
Definition: BKE_armature.h:50
float roll2
Definition: BKE_armature.h:72
float curve_in_x
Definition: BKE_armature.h:73
float curve_in_z
Definition: BKE_armature.h:73
float ease1
Definition: BKE_armature.h:75
float scale_out[3]
Definition: BKE_armature.h:76
float curve_out_x
Definition: BKE_armature.h:74
float head[3]
Definition: BKE_armature.h:53
void * next
Definition: DNA_ID.h:369
char name[66]
Definition: DNA_ID.h:378
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
char filepath[1024]
Definition: BKE_main.h:124
ListBase armatures
Definition: BKE_main.h:190
ListBase objects
Definition: BKE_main.h:170
short partype
struct bPose * pose
float parentinv[4][4]
float obmat[4][4]
struct AnimData * adt
struct Object * parent
void * data
void * data
Definition: RNA_types.h:38
struct RenderData r
struct AnimData * adt
ListBase bonebase
unsigned int layer
ListBase * edbo
ListBase constraints
IDProperty * prop
float scale_out[3]
struct Bone * bone
struct bPoseChannel * parent
float pose_tail[3]
struct bPoseChannel * next
float pose_mat[4][4]
ListBase chanbase
short flag
bAnimVizSettings avs
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
void(* ui)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:954
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
struct ReportList * reports
IDProperty * properties
struct uiLayout * layout
struct wmOperatorType * type
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479