Blender  V2.93
pose_slide.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_dlrbTree.h"
28 #include "BLI_math.h"
29 
30 #include "BLT_translation.h"
31 
32 #include "DNA_anim_types.h"
33 #include "DNA_armature_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_scene_types.h"
36 
37 #include "BKE_fcurve.h"
38 #include "BKE_nla.h"
39 
40 #include "BKE_context.h"
41 #include "BKE_layer.h"
42 #include "BKE_object.h"
43 #include "BKE_report.h"
44 #include "BKE_unit.h"
45 
46 #include "RNA_access.h"
47 #include "RNA_define.h"
48 
49 #include "WM_api.h"
50 #include "WM_types.h"
51 
52 #include "UI_interface.h"
53 
54 #include "ED_armature.h"
55 #include "ED_keyframes_draw.h"
56 #include "ED_markers.h"
57 #include "ED_numinput.h"
58 #include "ED_screen.h"
59 
60 #include "armature_intern.h"
61 
62 /* **************************************************** */
63 /* == POSE 'SLIDING' TOOLS ==
64  *
65  * A) Push & Relax, Breakdowner
66  * These tools provide the animator with various capabilities
67  * for interactively controlling the spacing of poses, but also
68  * for 'pushing' and/or 'relaxing' extremes as they see fit.
69  *
70  * B) Propagate
71  * This tool copies elements of the selected pose to successive
72  * keyframes, allowing the animator to go back and modify the poses
73  * for some "static" pose controls, without having to repeatedly
74  * doing a "next paste" dance.
75  *
76  * C) Pose Sculpting
77  * This is yet to be implemented, but the idea here is to use
78  * sculpting techniques to make it easier to pose rigs by allowing
79  * rigs to be manipulated using a familiar paint-based interface.
80  */
81 /* **************************************************** */
82 /* A) Push & Relax, Breakdowner */
83 
84 /* Temporary data shared between these operators */
85 typedef struct tPoseSlideOp {
94 
99 
101  int cframe;
102 
107 
109  short mode;
111  short flag;
112 
114  short channels;
116  short axislock;
117 
119  float percentage;
120 
123 
126 
127 typedef struct tPoseSlideObject {
128  Object *ob; /* active object that Pose Info comes from */
129  float prevFrameF; /* prevFrame, but in local action time (for F-Curve lookups to work) */
130  float nextFrameF; /* nextFrame, but in local action time (for F-Curve lookups to work) */
131  bool valid;
133 
134 /* Pose Sliding Modes */
135 typedef enum ePoseSlide_Modes {
136  POSESLIDE_PUSH = 0, /* exaggerate the pose... */
137  POSESLIDE_RELAX, /* soften the pose... */
138  POSESLIDE_BREAKDOWN, /* slide between the endpoint poses, finding a 'soft' spot */
142 
143 /* Transforms/Channels to Affect */
144 typedef enum ePoseSlide_Channels {
145  PS_TFM_ALL = 0, /* All transforms and properties */
146 
147  PS_TFM_LOC, /* Loc/Rot/Scale */
150 
151  PS_TFM_BBONE_SHAPE, /* Bendy Bones */
152 
153  PS_TFM_PROPS, /* Custom Properties */
155 
156 /* Property enum for ePoseSlide_Channels */
158  {PS_TFM_ALL,
159  "ALL",
160  0,
161  "All Properties",
162  "All properties, including transforms, bendy bone shape, and custom properties"},
163  {PS_TFM_LOC, "LOC", 0, "Location", "Location only"},
164  {PS_TFM_ROT, "ROT", 0, "Rotation", "Rotation only"},
165  {PS_TFM_SIZE, "SIZE", 0, "Scale", "Scale only"},
166  {PS_TFM_BBONE_SHAPE, "BBONE", 0, "Bendy Bone", "Bendy Bone shape properties"},
167  {PS_TFM_PROPS, "CUSTOM", 0, "Custom Properties", "Custom properties"},
168  {0, NULL, 0, NULL, NULL},
169 };
170 
171 /* Axis Locks */
172 typedef enum ePoseSlide_AxisLock {
173  PS_LOCK_X = (1 << 0),
174  PS_LOCK_Y = (1 << 1),
175  PS_LOCK_Z = (1 << 2),
177 
178 /* Property enum for ePoseSlide_AxisLock */
180  {0, "FREE", 0, "Free", "All axes are affected"},
181  {PS_LOCK_X, "X", 0, "X", "Only X-axis transforms are affected"},
182  {PS_LOCK_Y, "Y", 0, "Y", "Only Y-axis transforms are affected"},
183  {PS_LOCK_Z, "Z", 0, "Z", "Only Z-axis transforms are affected"},
184  /* TODO: Combinations? */
185  {0, NULL, 0, NULL, NULL},
186 };
187 
188 /* ------------------------------------ */
189 
190 /* operator init */
192 {
193  tPoseSlideOp *pso;
194 
195  /* init slide-op data */
196  pso = op->customdata = MEM_callocN(sizeof(tPoseSlideOp), "tPoseSlideOp");
197 
198  /* get info from context */
199  pso->scene = CTX_data_scene(C);
200  pso->area = CTX_wm_area(C); /* only really needed when doing modal() */
201  pso->region = CTX_wm_region(C); /* only really needed when doing modal() */
202 
203  pso->cframe = pso->scene->r.cfra;
204  pso->mode = mode;
205 
206  /* set range info from property values - these may get overridden for the invoke() */
207  pso->percentage = RNA_float_get(op->ptr, "factor");
208  pso->prevFrame = RNA_int_get(op->ptr, "prev_frame");
209  pso->nextFrame = RNA_int_get(op->ptr, "next_frame");
210 
211  /* get the set of properties/axes that can be operated on */
212  pso->channels = RNA_enum_get(op->ptr, "channels");
213  pso->axislock = RNA_enum_get(op->ptr, "axis_lock");
214 
215  /* for each Pose-Channel which gets affected, get the F-Curves for that channel
216  * and set the relevant transform flags... */
218 
222  "pose slide objects data");
223 
224  for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
225  tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
226  Object *ob_iter = poseAnim_object_get(objects[ob_index]);
227 
228  /* Ensure validity of the settings from the context. */
229  if (ob_iter == NULL) {
230  continue;
231  }
232 
233  ob_data->ob = ob_iter;
234  ob_data->valid = true;
235 
236  /* apply NLA mapping corrections so the frame lookups work */
238  ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
240  ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
241 
242  /* set depsgraph flags */
243  /* make sure the lock is set OK, unlock can be accidentally saved? */
244  ob_data->ob->pose->flag |= POSE_LOCKED;
245  ob_data->ob->pose->flag &= ~POSE_DO_UNLOCK;
246  }
247  MEM_freeN(objects);
248 
249  /* do basic initialize of RB-BST used for finding keyframes, but leave the filling of it up
250  * to the caller of this (usually only invoke() will do it, to make things more efficient).
251  */
252  BLI_dlrbTree_init(&pso->keys);
253 
254  /* Initialize numeric input. */
255  initNumInput(&pso->num);
256  pso->num.idx_max = 0; /* one axis */
257  pso->num.val_flag[0] |= NUM_NO_NEGATIVE;
258  pso->num.unit_type[0] = B_UNIT_NONE; /* percentages don't have any units... */
259 
260  /* return status is whether we've got all the data we were requested to get */
261  return 1;
262 }
263 
264 /* exiting the operator - free data */
265 static void pose_slide_exit(wmOperator *op)
266 {
267  tPoseSlideOp *pso = op->customdata;
268 
269  /* if data exists, clear its data and exit */
270  if (pso) {
271  /* free the temp pchan links and their data */
273 
274  /* free RB-BST for keyframes (if it contained data) */
275  BLI_dlrbTree_free(&pso->keys);
276 
277  if (pso->ob_data_array != NULL) {
278  MEM_freeN(pso->ob_data_array);
279  }
280 
281  /* free data itself */
282  MEM_freeN(pso);
283  }
284 
285  /* cleanup */
286  op->customdata = NULL;
287 }
288 
289 /* ------------------------------------ */
290 
291 /* helper for apply() / reset() - refresh the data */
293 {
294  /* wrapper around the generic version, allowing us to add some custom stuff later still */
295  for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
296  tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
297  if (ob_data->valid) {
298  poseAnim_mapping_refresh(C, pso->scene, ob_data->ob);
299  }
300  }
301 }
302 
308  Object *ob,
309  float *prevFrameF,
310  float *nextFrameF)
311 {
312  for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
313  tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
314  Object *ob_iter = ob_data->ob;
315 
316  if (ob_iter == ob) {
317  *prevFrameF = ob_data->prevFrameF;
318  *nextFrameF = ob_data->nextFrameF;
319  return true;
320  }
321  }
322  *prevFrameF = *nextFrameF = 0.0f;
323  return false;
324 }
325 
326 /* helper for apply() - perform sliding for some value */
327 static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, float *val)
328 {
329  float prevFrameF, nextFrameF;
330  float cframe = (float)pso->cframe;
331  float sVal, eVal;
332  float w1, w2;
333 
334  pose_frame_range_from_object_get(pso, ob, &prevFrameF, &nextFrameF);
335 
336  /* get keyframe values for endpoint poses to blend with */
337  /* previous/start */
338  sVal = evaluate_fcurve(fcu, prevFrameF);
339  /* next/end */
340  eVal = evaluate_fcurve(fcu, nextFrameF);
341 
342  /* calculate the relative weights of the endpoints */
343  if (pso->mode == POSESLIDE_BREAKDOWN) {
344  /* get weights from the percentage control */
345  w1 = pso->percentage; /* this must come second */
346  w2 = 1.0f - w1; /* this must come first */
347  }
348  else {
349  /* - these weights are derived from the relative distance of these
350  * poses from the current frame
351  * - they then get normalized so that they only sum up to 1
352  */
353  float wtot;
354 
355  w1 = cframe - (float)pso->prevFrame;
356  w2 = (float)pso->nextFrame - cframe;
357 
358  wtot = w1 + w2;
359  w1 = (w1 / wtot);
360  w2 = (w2 / wtot);
361  }
362 
363  /* Depending on the mode, calculate the new value:
364  * - In all of these, the start+end values are multiplied by w2 and w1 (respectively),
365  * since multiplication in another order would decrease
366  * the value the current frame is closer to.
367  */
368  switch (pso->mode) {
369  case POSESLIDE_PUSH: /* make the current pose more pronounced */
370  {
371  /* Slide the pose away from the breakdown pose in the timeline */
372  (*val) -= ((sVal * w2) + (eVal * w1) - (*val)) * pso->percentage;
373  break;
374  }
375  case POSESLIDE_RELAX: /* make the current pose more like its surrounding ones */
376  {
377  /* Slide the pose towards the breakdown pose in the timeline */
378  (*val) += ((sVal * w2) + (eVal * w1) - (*val)) * pso->percentage;
379  break;
380  }
381  case POSESLIDE_BREAKDOWN: /* make the current pose slide around between the endpoints */
382  {
383  /* Perform simple linear interpolation -
384  * coefficient for start must come from pso->percentage. */
385  /* TODO: make this use some kind of spline interpolation instead? */
386  (*val) = ((sVal * w2) + (eVal * w1));
387  break;
388  }
389  }
390 }
391 
392 /* helper for apply() - perform sliding for some 3-element vector */
394  tPChanFCurveLink *pfl,
395  float vec[3],
396  const char propName[])
397 {
398  LinkData *ld = NULL;
399  char *path = NULL;
400 
401  /* get the path to use... */
402  path = BLI_sprintfN("%s.%s", pfl->pchan_path, propName);
403 
404  /* using this path, find each matching F-Curve for the variables we're interested in */
405  while ((ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path))) {
406  FCurve *fcu = (FCurve *)ld->data;
407  const int idx = fcu->array_index;
408  const int lock = pso->axislock;
409 
410  /* check if this F-Curve is ok given the current axis locks */
411  BLI_assert(fcu->array_index < 3);
412 
413  if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) ||
414  ((lock & PS_LOCK_Z) && (idx == 2))) {
415  /* just work on these channels one by one... there's no interaction between values */
416  pose_slide_apply_val(pso, fcu, pfl->ob, &vec[fcu->array_index]);
417  }
418  }
419 
420  /* free the temp path we got */
421  MEM_freeN(path);
422 }
423 
424 /* helper for apply() - perform sliding for custom properties or bbone properties */
426  tPChanFCurveLink *pfl,
427  const char prop_prefix[])
428 {
429  PointerRNA ptr = {NULL};
430  LinkData *ld;
431  int len = strlen(pfl->pchan_path);
432 
433  /* setup pointer RNA for resolving paths */
435 
436  /* - custom properties are just denoted using ["..."][etc.] after the end of the base path,
437  * so just check for opening pair after the end of the path
438  * - bbone properties are similar, but they always start with a prefix "bbone_*",
439  * so a similar method should work here for those too
440  */
441  for (ld = pfl->fcurves.first; ld; ld = ld->next) {
442  FCurve *fcu = (FCurve *)ld->data;
443  const char *bPtr, *pPtr;
444 
445  if (fcu->rna_path == NULL) {
446  continue;
447  }
448 
449  /* do we have a match?
450  * - bPtr is the RNA Path with the standard part chopped off
451  * - pPtr is the chunk of the path which is left over
452  */
453  bPtr = strstr(fcu->rna_path, pfl->pchan_path) + len;
454  pPtr = strstr(bPtr, prop_prefix);
455 
456  if (pPtr) {
457  /* use RNA to try and get a handle on this property, then, assuming that it is just
458  * numerical, try and grab the value as a float for temp editing before setting back
459  */
460  PropertyRNA *prop = RNA_struct_find_property(&ptr, pPtr);
461 
462  if (prop) {
463  switch (RNA_property_type(prop)) {
464  /* continuous values that can be smoothly interpolated... */
465  case PROP_FLOAT: {
466  float tval = RNA_property_float_get(&ptr, prop);
467  pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
468  RNA_property_float_set(&ptr, prop, tval);
469  break;
470  }
471  case PROP_INT: {
472  float tval = (float)RNA_property_int_get(&ptr, prop);
473  pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
474  RNA_property_int_set(&ptr, prop, (int)tval);
475  break;
476  }
477 
478  /* values which can only take discrete values */
479  case PROP_BOOLEAN: {
480  float tval = (float)RNA_property_boolean_get(&ptr, prop);
481  pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
483  &ptr, prop, (int)tval); /* XXX: do we need threshold clamping here? */
484  break;
485  }
486  case PROP_ENUM: {
487  /* don't handle this case - these don't usually represent interchangeable
488  * set of values which should be interpolated between
489  */
490  break;
491  }
492 
493  default:
494  /* cannot handle */
495  // printf("Cannot Pose Slide non-numerical property\n");
496  break;
497  }
498  }
499  }
500  }
501 }
502 
503 /* helper for apply() - perform sliding for quaternion rotations (using quat blending) */
505 {
506  FCurve *fcu_w = NULL, *fcu_x = NULL, *fcu_y = NULL, *fcu_z = NULL;
507  bPoseChannel *pchan = pfl->pchan;
508  LinkData *ld = NULL;
509  char *path = NULL;
510  float cframe;
511  float prevFrameF, nextFrameF;
512 
513  if (!pose_frame_range_from_object_get(pso, pfl->ob, &prevFrameF, &nextFrameF)) {
514  BLI_assert(!"Invalid pfl data");
515  return;
516  }
517 
518  /* get the path to use - this should be quaternion rotations only (needs care) */
519  path = BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation_quaternion");
520 
521  /* get the current frame number */
522  cframe = (float)pso->cframe;
523 
524  /* using this path, find each matching F-Curve for the variables we're interested in */
525  while ((ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path))) {
526  FCurve *fcu = (FCurve *)ld->data;
527 
528  /* assign this F-Curve to one of the relevant pointers... */
529  switch (fcu->array_index) {
530  case 3: /* z */
531  fcu_z = fcu;
532  break;
533  case 2: /* y */
534  fcu_y = fcu;
535  break;
536  case 1: /* x */
537  fcu_x = fcu;
538  break;
539  case 0: /* w */
540  fcu_w = fcu;
541  break;
542  }
543  }
544 
545  /* only if all channels exist, proceed */
546  if (fcu_w && fcu_x && fcu_y && fcu_z) {
547  float quat_final[4];
548 
549  /* Perform blending. */
551  float quat_prev[4], quat_next[4];
552 
553  quat_prev[0] = evaluate_fcurve(fcu_w, prevFrameF);
554  quat_prev[1] = evaluate_fcurve(fcu_x, prevFrameF);
555  quat_prev[2] = evaluate_fcurve(fcu_y, prevFrameF);
556  quat_prev[3] = evaluate_fcurve(fcu_z, prevFrameF);
557 
558  quat_next[0] = evaluate_fcurve(fcu_w, nextFrameF);
559  quat_next[1] = evaluate_fcurve(fcu_x, nextFrameF);
560  quat_next[2] = evaluate_fcurve(fcu_y, nextFrameF);
561  quat_next[3] = evaluate_fcurve(fcu_z, nextFrameF);
562 
563  normalize_qt(quat_prev);
564  normalize_qt(quat_next);
565 
566  if (pso->mode == POSESLIDE_BREAKDOWN) {
567  /* Just perform the interpolation between quat_prev and
568  * quat_next using pso->factor as a guide. */
569  interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->percentage);
570  }
571  else {
572  float quat_curr[4], quat_breakdown[4];
573 
574  normalize_qt_qt(quat_curr, pchan->quat);
575 
576  /* Compute breakdown based on actual frame range. */
577  const float factor = (cframe - pso->prevFrame) / (float)(pso->nextFrame - pso->prevFrame);
578 
579  interp_qt_qtqt(quat_breakdown, quat_prev, quat_next, factor);
580 
581  if (pso->mode == POSESLIDE_PUSH) {
583  quat_final, quat_breakdown, quat_curr, 1.0f + pso->percentage);
584  }
585  else {
587  interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, pso->percentage);
588  }
589  }
590  }
591 
592  /* Apply final to the pose bone, keeping compatible for similar keyframe positions. */
593  quat_to_compatible_quat(pchan->quat, quat_final, pchan->quat);
594  }
595 
596  /* free the path now */
597  MEM_freeN(path);
598 }
599 
600 static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], float default_value)
601 {
602  /* We only slide to the rest pose. So only use the default rest pose value */
603  const int lock = pso->axislock;
604  for (int idx = 0; idx < 3; idx++) {
605  if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) ||
606  ((lock & PS_LOCK_Z) && (idx == 2))) {
607  float diff_val = default_value - vec[idx];
608  if (pso->mode == POSESLIDE_RELAX_REST) {
609  vec[idx] += pso->percentage * diff_val;
610  }
611  else {
612  /* Push */
613  vec[idx] -= pso->percentage * diff_val;
614  }
615  }
616  }
617 }
618 
619 static void pose_slide_rest_pose_apply_other_rot(tPoseSlideOp *pso, float vec[4], bool quat)
620 {
621  /* We only slide to the rest pose. So only use the default rest pose value */
622  float default_values[] = {1.0f, 0.0f, 0.0f, 0.0f};
623  if (!quat) {
624  /* Axis Angle */
625  default_values[0] = 0.0f;
626  default_values[2] = 1.0f;
627  }
628  for (int idx = 0; idx < 4; idx++) {
629  float diff_val = default_values[idx] - vec[idx];
630  if (pso->mode == POSESLIDE_RELAX_REST) {
631  vec[idx] += pso->percentage * diff_val;
632  }
633  else {
634  /* Push */
635  vec[idx] -= pso->percentage * diff_val;
636  }
637  }
638 }
639 
640 /* apply() - perform the pose sliding between the current pose and the rest pose */
642 {
643  tPChanFCurveLink *pfl;
644 
645  /* for each link, handle each set of transforms */
646  for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
647  /* valid transforms for each PoseChannel should have been noted already
648  * - sliding the pose should be a straightforward exercise for location+rotation,
649  * but rotations get more complicated since we may want to use quaternion blending
650  * for quaternions instead...
651  */
652  bPoseChannel *pchan = pfl->pchan;
653 
654  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) {
655  /* calculate these for the 'location' vector, and use location curves */
656  pose_slide_rest_pose_apply_vec3(pso, pchan->loc, 0.0f);
657  }
658 
659  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) {
660  /* calculate these for the 'scale' vector, and use scale curves */
661  pose_slide_rest_pose_apply_vec3(pso, pchan->size, 1.0f);
662  }
663 
664  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) {
665  /* everything depends on the rotation mode */
666  if (pchan->rotmode > 0) {
667  /* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */
668  pose_slide_rest_pose_apply_vec3(pso, pchan->eul, 0.0f);
669  }
670  else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
671  pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, false);
672  }
673  else {
674  /* quaternions - use quaternion blending */
675  pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, true);
676  }
677  }
678 
679  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) {
680  /* bbone properties - they all start a "bbone_" prefix */
681  /* TODO Not implemented */
682  // pose_slide_apply_props(pso, pfl, "bbone_");
683  }
684 
685  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
686  /* Not strictly a transform, but custom properties contribute
687  * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */
688  /* TODO Not implemented */
689  // pose_slide_apply_props(pso, pfl, "[\"");
690  }
691  }
692 
693  /* depsgraph updates + redraws */
694  pose_slide_refresh(C, pso);
695 }
696 
697 /* apply() - perform the pose sliding based on weighting various poses */
699 {
700  tPChanFCurveLink *pfl;
701 
702  /* Sanitize the frame ranges. */
703  if (pso->prevFrame == pso->nextFrame) {
704  /* move out one step either side */
705  pso->prevFrame--;
706  pso->nextFrame++;
707 
708  for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
709  tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
710 
711  if (!ob_data->valid) {
712  continue;
713  }
714 
715  /* apply NLA mapping corrections so the frame lookups work */
717  ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
719  ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
720  }
721  }
722 
723  /* for each link, handle each set of transforms */
724  for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
725  /* valid transforms for each PoseChannel should have been noted already
726  * - sliding the pose should be a straightforward exercise for location+rotation,
727  * but rotations get more complicated since we may want to use quaternion blending
728  * for quaternions instead...
729  */
730  bPoseChannel *pchan = pfl->pchan;
731 
732  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) {
733  /* calculate these for the 'location' vector, and use location curves */
734  pose_slide_apply_vec3(pso, pfl, pchan->loc, "location");
735  }
736 
737  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) {
738  /* calculate these for the 'scale' vector, and use scale curves */
739  pose_slide_apply_vec3(pso, pfl, pchan->size, "scale");
740  }
741 
742  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) {
743  /* everything depends on the rotation mode */
744  if (pchan->rotmode > 0) {
745  /* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */
746  pose_slide_apply_vec3(pso, pfl, pchan->eul, "rotation_euler");
747  }
748  else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
749  /* TODO: need to figure out how to do this! */
750  }
751  else {
752  /* quaternions - use quaternion blending */
753  pose_slide_apply_quat(pso, pfl);
754  }
755  }
756 
757  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) {
758  /* bbone properties - they all start a "bbone_" prefix */
759  pose_slide_apply_props(pso, pfl, "bbone_");
760  }
761 
762  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
763  /* Not strictly a transform, but custom properties contribute
764  * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */
765  pose_slide_apply_props(pso, pfl, "[\"");
766  }
767  }
768 
769  /* depsgraph updates + redraws */
770  pose_slide_refresh(C, pso);
771 }
772 
773 /* perform auto-key-framing after changes were made + confirmed */
775 {
776  /* wrapper around the generic call */
777  poseAnim_mapping_autoKeyframe(C, pso->scene, &pso->pfLinks, (float)pso->cframe);
778 }
779 
780 /* reset changes made to current pose */
782 {
783  /* wrapper around the generic call, so that custom stuff can be added later */
785 }
786 
787 /* ------------------------------------ */
788 
789 /* draw percentage indicator in header */
790 /* TODO: Include hints about locks here... */
792 {
793  char status_str[UI_MAX_DRAW_STR];
794  char limits_str[UI_MAX_DRAW_STR];
795  char axis_str[50];
796  char mode_str[32];
797 
798  switch (pso->mode) {
799  case POSESLIDE_PUSH:
800  strcpy(mode_str, TIP_("Push Pose"));
801  break;
802  case POSESLIDE_RELAX:
803  strcpy(mode_str, TIP_("Relax Pose"));
804  break;
805  case POSESLIDE_BREAKDOWN:
806  strcpy(mode_str, TIP_("Breakdown"));
807  break;
808 
809  default:
810  /* unknown */
811  strcpy(mode_str, TIP_("Sliding-Tool"));
812  break;
813  }
814 
815  switch (pso->axislock) {
816  case PS_LOCK_X:
817  BLI_strncpy(axis_str, TIP_("[X]/Y/Z axis only (X to clear)"), sizeof(axis_str));
818  break;
819  case PS_LOCK_Y:
820  BLI_strncpy(axis_str, TIP_("X/[Y]/Z axis only (Y to clear)"), sizeof(axis_str));
821  break;
822  case PS_LOCK_Z:
823  BLI_strncpy(axis_str, TIP_("X/Y/[Z] axis only (Z to clear)"), sizeof(axis_str));
824  break;
825 
826  default:
828  BLI_strncpy(axis_str, TIP_("X/Y/Z = Axis Constraint"), sizeof(axis_str));
829  }
830  else {
831  axis_str[0] = '\0';
832  }
833  break;
834  }
835 
836  switch (pso->channels) {
837  case PS_TFM_LOC:
838  BLI_snprintf(limits_str,
839  sizeof(limits_str),
840  TIP_("[G]/R/S/B/C - Location only (G to clear) | %s"),
841  axis_str);
842  break;
843  case PS_TFM_ROT:
844  BLI_snprintf(limits_str,
845  sizeof(limits_str),
846  TIP_("G/[R]/S/B/C - Rotation only (R to clear) | %s"),
847  axis_str);
848  break;
849  case PS_TFM_SIZE:
850  BLI_snprintf(limits_str,
851  sizeof(limits_str),
852  TIP_("G/R/[S]/B/C - Scale only (S to clear) | %s"),
853  axis_str);
854  break;
855  case PS_TFM_BBONE_SHAPE:
856  BLI_strncpy(limits_str,
857  TIP_("G/R/S/[B]/C - Bendy Bone properties only (B to clear) | %s"),
858  sizeof(limits_str));
859  break;
860  case PS_TFM_PROPS:
861  BLI_strncpy(limits_str,
862  TIP_("G/R/S/B/[C] - Custom Properties only (C to clear) | %s"),
863  sizeof(limits_str));
864  break;
865  default:
866  BLI_strncpy(
867  limits_str, TIP_("G/R/S/B/C - Limit to Transform/Property Set"), sizeof(limits_str));
868  break;
869  }
870 
871  if (hasNumInput(&pso->num)) {
872  Scene *scene = pso->scene;
873  char str_ofs[NUM_STR_REP_LEN];
874 
875  outputNumInput(&pso->num, str_ofs, &scene->unit);
876 
877  BLI_snprintf(
878  status_str, sizeof(status_str), "%s: %s | %s", mode_str, str_ofs, limits_str);
879  }
880  else {
881  BLI_snprintf(status_str,
882  sizeof(status_str),
883  "%s: %d %% | %s",
884  mode_str,
885  (int)(pso->percentage * 100.0f),
886  limits_str);
887  }
888 
889  ED_area_status_text(pso->area, status_str);
890 }
891 
892 /* common code for invoke() methods */
894 {
895  tPChanFCurveLink *pfl;
896  wmWindow *win = CTX_wm_window(C);
897 
898  /* for each link, add all its keyframes to the search tree */
899  for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
900  LinkData *ld;
901 
902  /* do this for each F-Curve */
903  for (ld = pfl->fcurves.first; ld; ld = ld->next) {
904  FCurve *fcu = (FCurve *)ld->data;
905  fcurve_to_keylist(pfl->ob->adt, fcu, &pso->keys, 0);
906  }
907  }
908 
909  /* cancel if no keyframes found... */
910  if (pso->keys.root) {
911  ActKeyColumn *ak;
912  float cframe = (float)pso->cframe;
913 
914  /* firstly, check if the current frame is a keyframe... */
916 
917  if (ak == NULL) {
918  /* current frame is not a keyframe, so search */
920  &pso->keys, compare_ak_cfraPtr, &cframe);
922  &pso->keys, compare_ak_cfraPtr, &cframe);
923 
924  /* new set the frames */
925  /* prev frame */
926  pso->prevFrame = (pk) ? (pk->cfra) : (pso->cframe - 1);
927  RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
928  /* next frame */
929  pso->nextFrame = (nk) ? (nk->cfra) : (pso->cframe + 1);
930  RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
931  }
932  else {
933  /* current frame itself is a keyframe, so just take keyframes on either side */
934  /* prev frame */
935  pso->prevFrame = (ak->prev) ? (ak->prev->cfra) : (pso->cframe - 1);
936  RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
937  /* next frame */
938  pso->nextFrame = (ak->next) ? (ak->next->cfra) : (pso->cframe + 1);
939  RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
940  }
941 
942  /* apply NLA mapping corrections so the frame lookups work */
943  for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
944  tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
945  if (ob_data->valid) {
947  ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
949  ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
950  }
951  }
952  }
953  else {
954  BKE_report(op->reports, RPT_ERROR, "No keyframes to slide between");
955  pose_slide_exit(op);
956  return OPERATOR_CANCELLED;
957  }
958 
959  /* initial apply for operator... */
960  /* TODO: need to calculate percentage for initial round too... */
962  pose_slide_apply(C, pso);
963  }
964  else {
966  }
967 
968  /* depsgraph updates + redraws */
969  pose_slide_refresh(C, pso);
970 
971  /* set cursor to indicate modal */
973 
974  /* header print */
976 
977  /* add a modal handler for this operator */
979  return OPERATOR_RUNNING_MODAL;
980 }
981 
982 /* calculate percentage based on position of mouse (we only use x-axis for now.
983  * since this is more convenient for users to do), and store new percentage value
984  */
986  wmOperator *op,
987  const wmEvent *event)
988 {
989  pso->percentage = (event->x - pso->region->winrct.xmin) / ((float)pso->region->winx);
990  RNA_float_set(op->ptr, "factor", pso->percentage);
991 }
992 
993 /* handle an event to toggle channels mode */
995  tPoseSlideOp *pso,
996  ePoseSlide_Channels channel)
997 {
998  /* Turn channel on or off? */
999  if (pso->channels == channel) {
1000  /* Already limiting to transform only, so pressing this again turns it off */
1001  pso->channels = PS_TFM_ALL;
1002  }
1003  else {
1004  /* Only this set of channels */
1005  pso->channels = channel;
1006  }
1007  RNA_enum_set(op->ptr, "channels", pso->channels);
1008 
1009  /* Reset axis limits too for good measure */
1010  pso->axislock = 0;
1011  RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
1012 }
1013 
1014 /* handle an event to toggle axis locks - returns whether any change in state is needed */
1016  tPoseSlideOp *pso,
1017  ePoseSlide_AxisLock axis)
1018 {
1019  /* Axis can only be set when a transform is set - it doesn't make sense otherwise */
1021  pso->axislock = 0;
1022  RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
1023  return false;
1024  }
1025 
1026  /* Turn on or off? */
1027  if (pso->axislock == axis) {
1028  /* Already limiting on this axis, so turn off */
1029  pso->axislock = 0;
1030  }
1031  else {
1032  /* Only this axis */
1033  pso->axislock = axis;
1034  }
1035  RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
1036 
1037  /* Setting changed, so pose update is needed */
1038  return true;
1039 }
1040 
1041 /* common code for modal() */
1042 static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
1043 {
1044  tPoseSlideOp *pso = op->customdata;
1045  wmWindow *win = CTX_wm_window(C);
1046  bool do_pose_update = false;
1047 
1048  const bool has_numinput = hasNumInput(&pso->num);
1049 
1050  switch (event->type) {
1051  case LEFTMOUSE: /* confirm */
1052  case EVT_RETKEY:
1053  case EVT_PADENTER: {
1054  if (event->val == KM_PRESS) {
1055  /* return to normal cursor and header status */
1056  ED_area_status_text(pso->area, NULL);
1058 
1059  /* insert keyframes as required... */
1060  pose_slide_autoKeyframe(C, pso);
1061  pose_slide_exit(op);
1062 
1063  /* done! */
1064  return OPERATOR_FINISHED;
1065  }
1066  break;
1067  }
1068 
1069  case EVT_ESCKEY: /* cancel */
1070  case RIGHTMOUSE: {
1071  if (event->val == KM_PRESS) {
1072  /* return to normal cursor and header status */
1073  ED_area_status_text(pso->area, NULL);
1075 
1076  /* reset transforms back to original state */
1077  pose_slide_reset(pso);
1078 
1079  /* depsgraph updates + redraws */
1080  pose_slide_refresh(C, pso);
1081 
1082  /* clean up temp data */
1083  pose_slide_exit(op);
1084 
1085  /* canceled! */
1086  return OPERATOR_CANCELLED;
1087  }
1088  break;
1089  }
1090 
1091  /* Percentage Change... */
1092  case MOUSEMOVE: /* calculate new position */
1093  {
1094  /* only handle mousemove if not doing numinput */
1095  if (has_numinput == false) {
1096  /* update percentage based on position of mouse */
1097  pose_slide_mouse_update_percentage(pso, op, event);
1098 
1099  /* update pose to reflect the new values (see below) */
1100  do_pose_update = true;
1101  }
1102  break;
1103  }
1104  default: {
1105  if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) {
1106  float value;
1107 
1108  /* Grab percentage from numeric input, and store this new value for redo
1109  * NOTE: users see ints, while internally we use a 0-1 float
1110  */
1111  value = pso->percentage * 100.0f;
1112  applyNumInput(&pso->num, &value);
1113 
1114  pso->percentage = value / 100.0f;
1115  CLAMP(pso->percentage, 0.0f, 1.0f);
1116  RNA_float_set(op->ptr, "factor", pso->percentage);
1117 
1118  /* Update pose to reflect the new values (see below) */
1119  do_pose_update = true;
1120  break;
1121  }
1122  if (event->val == KM_PRESS) {
1123  switch (event->type) {
1124  /* Transform Channel Limits */
1125  /* XXX: Replace these hard-coded hotkeys with a modal-map that can be customized. */
1126  case EVT_GKEY: /* Location */
1127  {
1129  do_pose_update = true;
1130  break;
1131  }
1132  case EVT_RKEY: /* Rotation */
1133  {
1135  do_pose_update = true;
1136  break;
1137  }
1138  case EVT_SKEY: /* Scale */
1139  {
1141  do_pose_update = true;
1142  break;
1143  }
1144  case EVT_BKEY: /* Bendy Bones */
1145  {
1147  do_pose_update = true;
1148  break;
1149  }
1150  case EVT_CKEY: /* Custom Properties */
1151  {
1153  do_pose_update = true;
1154  break;
1155  }
1156 
1157  /* Axis Locks */
1158  /* XXX: Hardcoded... */
1159  case EVT_XKEY: {
1160  if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_X)) {
1161  do_pose_update = true;
1162  }
1163  break;
1164  }
1165  case EVT_YKEY: {
1166  if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Y)) {
1167  do_pose_update = true;
1168  }
1169  break;
1170  }
1171  case EVT_ZKEY: {
1172  if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Z)) {
1173  do_pose_update = true;
1174  }
1175  break;
1176  }
1177 
1178  default: /* Some other unhandled key... */
1179  break;
1180  }
1181  }
1182  else {
1183  /* unhandled event - maybe it was some view manipulation? */
1184  /* allow to pass through */
1186  }
1187  }
1188  }
1189 
1190  /* Perform pose updates - in response to some user action
1191  * (e.g. pressing a key or moving the mouse). */
1192  if (do_pose_update) {
1193  /* update percentage indicator in header */
1195 
1196  /* reset transforms (to avoid accumulation errors) */
1197  pose_slide_reset(pso);
1198 
1199  /* apply... */
1201  pose_slide_apply(C, pso);
1202  }
1203  else {
1205  }
1206  }
1207 
1208  /* still running... */
1209  return OPERATOR_RUNNING_MODAL;
1210 }
1211 
1212 /* common code for cancel() */
1214 {
1215  /* cleanup and done */
1216  pose_slide_exit(op);
1217 }
1218 
1219 /* common code for exec() methods */
1221 {
1222  /* settings should have been set up ok for applying, so just apply! */
1224  pose_slide_apply(C, pso);
1225  }
1226  else {
1228  }
1229 
1230  /* insert keyframes if needed */
1231  pose_slide_autoKeyframe(C, pso);
1232 
1233  /* cleanup and done */
1234  pose_slide_exit(op);
1235 
1236  return OPERATOR_FINISHED;
1237 }
1238 
1243 {
1244  PropertyRNA *prop;
1245 
1246  prop = RNA_def_float_factor(ot->srna,
1247  "factor",
1248  0.5f,
1249  0.0f,
1250  1.0f,
1251  "Factor",
1252  "Weighting factor for which keyframe is favored more",
1253  0.0,
1254  1.0);
1256 
1257  prop = RNA_def_int(ot->srna,
1258  "prev_frame",
1259  0,
1260  MINAFRAME,
1261  MAXFRAME,
1262  "Previous Keyframe",
1263  "Frame number of keyframe immediately before the current frame",
1264  0,
1265  50);
1267 
1268  prop = RNA_def_int(ot->srna,
1269  "next_frame",
1270  0,
1271  MINAFRAME,
1272  MAXFRAME,
1273  "Next Keyframe",
1274  "Frame number of keyframe immediately after the current frame",
1275  0,
1276  50);
1278 
1279  prop = RNA_def_enum(ot->srna,
1280  "channels",
1282  PS_TFM_ALL,
1283  "Channels",
1284  "Set of properties that are affected");
1286  prop = RNA_def_enum(ot->srna,
1287  "axis_lock",
1289  0,
1290  "Axis Lock",
1291  "Transform axis to restrict effects to");
1293 }
1294 
1295 /* ------------------------------------ */
1296 
1297 /* invoke() - for 'push from breakdown' mode */
1298 static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1299 {
1300  tPoseSlideOp *pso;
1301 
1302  /* initialize data */
1303  if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
1304  pose_slide_exit(op);
1305  return OPERATOR_CANCELLED;
1306  }
1307 
1308  pso = op->customdata;
1309 
1310  /* Initialize percentage so that it won't pop on first mouse move. */
1311  pose_slide_mouse_update_percentage(pso, op, event);
1312 
1313  /* do common setup work */
1314  return pose_slide_invoke_common(C, op, pso);
1315 }
1316 
1317 /* exec() - for push */
1319 {
1320  tPoseSlideOp *pso;
1321 
1322  /* initialize data (from RNA-props) */
1323  if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
1324  pose_slide_exit(op);
1325  return OPERATOR_CANCELLED;
1326  }
1327 
1328  pso = op->customdata;
1329 
1330  /* do common exec work */
1331  return pose_slide_exec_common(C, op, pso);
1332 }
1333 
1335 {
1336  /* identifiers */
1337  ot->name = "Push Pose from Breakdown";
1338  ot->idname = "POSE_OT_push";
1339  ot->description = "Exaggerate the current pose in regards to the breakdown pose";
1340 
1341  /* callbacks */
1347 
1348  /* flags */
1350 
1351  /* Properties */
1353 }
1354 
1355 /* ........................ */
1356 
1357 /* invoke() - for 'relax to breakdown' mode */
1358 static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1359 {
1360  tPoseSlideOp *pso;
1361 
1362  /* initialize data */
1363  if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
1364  pose_slide_exit(op);
1365  return OPERATOR_CANCELLED;
1366  }
1367 
1368  pso = op->customdata;
1369 
1370  /* Initialize percentage so that it won't pop on first mouse move. */
1371  pose_slide_mouse_update_percentage(pso, op, event);
1372 
1373  /* do common setup work */
1374  return pose_slide_invoke_common(C, op, pso);
1375 }
1376 
1377 /* exec() - for relax */
1379 {
1380  tPoseSlideOp *pso;
1381 
1382  /* initialize data (from RNA-props) */
1383  if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
1384  pose_slide_exit(op);
1385  return OPERATOR_CANCELLED;
1386  }
1387 
1388  pso = op->customdata;
1389 
1390  /* do common exec work */
1391  return pose_slide_exec_common(C, op, pso);
1392 }
1393 
1395 {
1396  /* identifiers */
1397  ot->name = "Relax Pose to Breakdown";
1398  ot->idname = "POSE_OT_relax";
1399  ot->description = "Make the current pose more similar to its breakdown pose";
1400 
1401  /* callbacks */
1407 
1408  /* flags */
1410 
1411  /* Properties */
1413 }
1414 
1415 /* ........................ */
1416 /* invoke() - for 'push from rest pose' mode */
1418 {
1419  tPoseSlideOp *pso;
1420 
1421  /* initialize data */
1422  if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) {
1423  pose_slide_exit(op);
1424  return OPERATOR_CANCELLED;
1425  }
1426 
1427  pso = op->customdata;
1428 
1429  /* Initialize percentage so that it won't pop on first mouse move. */
1430  pose_slide_mouse_update_percentage(pso, op, event);
1431 
1432  /* do common setup work */
1433  return pose_slide_invoke_common(C, op, pso);
1434 }
1435 
1436 /* exec() - for push */
1438 {
1439  tPoseSlideOp *pso;
1440 
1441  /* initialize data (from RNA-props) */
1442  if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) {
1443  pose_slide_exit(op);
1444  return OPERATOR_CANCELLED;
1445  }
1446 
1447  pso = op->customdata;
1448 
1449  /* do common exec work */
1450  return pose_slide_exec_common(C, op, pso);
1451 }
1452 
1454 {
1455  /* identifiers */
1456  ot->name = "Push Pose from Rest Pose";
1457  ot->idname = "POSE_OT_push_rest";
1458  ot->description = "Push the current pose further away from the rest pose";
1459 
1460  /* callbacks */
1466 
1467  /* flags */
1469 
1470  /* Properties */
1472 }
1473 
1474 /* ........................ */
1475 
1476 /* invoke() - for 'relax' mode */
1478 {
1479  tPoseSlideOp *pso;
1480 
1481  /* initialize data */
1482  if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) {
1483  pose_slide_exit(op);
1484  return OPERATOR_CANCELLED;
1485  }
1486 
1487  pso = op->customdata;
1488 
1489  /* Initialize percentage so that it won't pop on first mouse move. */
1490  pose_slide_mouse_update_percentage(pso, op, event);
1491 
1492  /* do common setup work */
1493  return pose_slide_invoke_common(C, op, pso);
1494 }
1495 
1496 /* exec() - for relax */
1498 {
1499  tPoseSlideOp *pso;
1500 
1501  /* initialize data (from RNA-props) */
1502  if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) {
1503  pose_slide_exit(op);
1504  return OPERATOR_CANCELLED;
1505  }
1506 
1507  pso = op->customdata;
1508 
1509  /* do common exec work */
1510  return pose_slide_exec_common(C, op, pso);
1511 }
1512 
1514 {
1515  /* identifiers */
1516  ot->name = "Relax Pose to Rest Pose";
1517  ot->idname = "POSE_OT_relax_rest";
1518  ot->description = "Make the current pose more similar to the rest pose";
1519 
1520  /* callbacks */
1526 
1527  /* flags */
1529 
1530  /* Properties */
1532 }
1533 
1534 /* ........................ */
1535 
1536 /* invoke() - for 'breakdown' mode */
1538 {
1539  tPoseSlideOp *pso;
1540 
1541  /* initialize data */
1542  if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
1543  pose_slide_exit(op);
1544  return OPERATOR_CANCELLED;
1545  }
1546 
1547  pso = op->customdata;
1548 
1549  /* Initialize percentage so that it won't pop on first mouse move. */
1550  pose_slide_mouse_update_percentage(pso, op, event);
1551 
1552  /* do common setup work */
1553  return pose_slide_invoke_common(C, op, pso);
1554 }
1555 
1556 /* exec() - for breakdown */
1558 {
1559  tPoseSlideOp *pso;
1560 
1561  /* initialize data (from RNA-props) */
1562  if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
1563  pose_slide_exit(op);
1564  return OPERATOR_CANCELLED;
1565  }
1566 
1567  pso = op->customdata;
1568 
1569  /* do common exec work */
1570  return pose_slide_exec_common(C, op, pso);
1571 }
1572 
1574 {
1575  /* identifiers */
1576  ot->name = "Pose Breakdowner";
1577  ot->idname = "POSE_OT_breakdown";
1578  ot->description = "Create a suitable breakdown pose on the current frame";
1579 
1580  /* callbacks */
1586 
1587  /* flags */
1589 
1590  /* Properties */
1592 }
1593 
1594 /* **************************************************** */
1595 /* B) Pose Propagate */
1596 
1597 /* "termination conditions" - i.e. when we stop */
1599  /* stop after the current hold ends */
1601  /* only do on the last keyframe */
1603  /* stop after the next keyframe */
1605  /* stop after the specified frame */
1607  /* stop when we run out of keyframes */
1609 
1610  /* only do on keyframes that are selected */
1612  /* only do on the frames where markers are selected */
1615 
1616 /* Termination data needed for some modes -
1617  * assumes only one of these entries will be needed at a time. */
1619  /* smart holds + before frame: frame number to stop on */
1620  float end_frame;
1621 
1622  /* selected markers: listbase for CfraElem's marking these frames */
1625 
1626 /* --------------------------------- */
1627 
1628 /* get frame on which the "hold" for the bone ends
1629  * XXX: this may not really work that well if a bone moves on some channels and not others
1630  * if this happens to be a major issue, scrap this, and just make this happen
1631  * independently per F-Curve
1632  */
1633 static float pose_propagate_get_boneHoldEndFrame(tPChanFCurveLink *pfl, float startFrame)
1634 {
1635  DLRBT_Tree keys;
1636 
1637  Object *ob = pfl->ob;
1638  AnimData *adt = ob->adt;
1639  LinkData *ld;
1640  float endFrame = startFrame;
1641 
1642  /* set up optimized data-structures for searching for relevant keyframes + holds */
1643  BLI_dlrbTree_init(&keys);
1644 
1645  for (ld = pfl->fcurves.first; ld; ld = ld->next) {
1646  FCurve *fcu = (FCurve *)ld->data;
1647  fcurve_to_keylist(adt, fcu, &keys, 0);
1648  }
1649 
1650  /* find the long keyframe (i.e. hold), and hence obtain the endFrame value
1651  * - the best case would be one that starts on the frame itself
1652  */
1654  &keys, compare_ak_cfraPtr, &startFrame);
1655 
1656  /* There are only two cases for no-exact match:
1657  * 1) the current frame is just before another key but not on a key itself
1658  * 2) the current frame is on a key, but that key doesn't link to the next
1659  *
1660  * If we've got the first case, then we can search for another block,
1661  * otherwise forget it, as we'd be overwriting some valid data.
1662  */
1663  if (ab == NULL) {
1664  /* we've got case 1, so try the one after */
1665  ab = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &startFrame);
1666 
1668  /* try the block before this frame then as last resort */
1669  ab = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &startFrame);
1670  }
1671  }
1672 
1673  /* whatever happens, stop searching now... */
1675  /* restrict range to just the frame itself
1676  * i.e. everything is in motion, so no holds to safely overwrite
1677  */
1678  ab = NULL;
1679  }
1680 
1681  /* check if we can go any further than we've already gone */
1682  if (ab) {
1683  /* go to next if it is also valid and meets "extension" criteria */
1684  while (ab->next) {
1685  ActKeyColumn *abn = ab->next;
1686 
1687  /* must be valid */
1689  break;
1690  }
1691  /* should have the same number of curves */
1692  if (ab->totblock != abn->totblock) {
1693  break;
1694  }
1695 
1696  /* we can extend the bounds to the end of this "next" block now */
1697  ab = abn;
1698  }
1699 
1700  /* end frame can now take the value of the end of the block */
1701  endFrame = ab->next->cfra;
1702  }
1703 
1704  /* free temp memory */
1705  BLI_dlrbTree_free(&keys);
1706 
1707  /* return the end frame we've found */
1708  return endFrame;
1709 }
1710 
1711 /* get reference value from F-Curve using RNA */
1712 static bool pose_propagate_get_refVal(Object *ob, FCurve *fcu, float *value)
1713 {
1714  PointerRNA id_ptr, ptr;
1715  PropertyRNA *prop;
1716  bool found = false;
1717 
1718  /* base pointer is always the object -> id_ptr */
1719  RNA_id_pointer_create(&ob->id, &id_ptr);
1720 
1721  /* resolve the property... */
1722  if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
1723  if (RNA_property_array_check(prop)) {
1724  /* array */
1725  if (fcu->array_index < RNA_property_array_length(&ptr, prop)) {
1726  found = true;
1727  switch (RNA_property_type(prop)) {
1728  case PROP_BOOLEAN:
1729  *value = (float)RNA_property_boolean_get_index(&ptr, prop, fcu->array_index);
1730  break;
1731  case PROP_INT:
1732  *value = (float)RNA_property_int_get_index(&ptr, prop, fcu->array_index);
1733  break;
1734  case PROP_FLOAT:
1735  *value = RNA_property_float_get_index(&ptr, prop, fcu->array_index);
1736  break;
1737  default:
1738  found = false;
1739  break;
1740  }
1741  }
1742  }
1743  else {
1744  /* not an array */
1745  found = true;
1746  switch (RNA_property_type(prop)) {
1747  case PROP_BOOLEAN:
1748  *value = (float)RNA_property_boolean_get(&ptr, prop);
1749  break;
1750  case PROP_INT:
1751  *value = (float)RNA_property_int_get(&ptr, prop);
1752  break;
1753  case PROP_ENUM:
1754  *value = (float)RNA_property_enum_get(&ptr, prop);
1755  break;
1756  case PROP_FLOAT:
1757  *value = RNA_property_float_get(&ptr, prop);
1758  break;
1759  default:
1760  found = false;
1761  break;
1762  }
1763  }
1764  }
1765 
1766  return found;
1767 }
1768 
1769 /* propagate just works along each F-Curve in turn */
1771  wmOperator *op, Object *ob, FCurve *fcu, float startFrame, tPosePropagate_ModeData modeData)
1772 {
1773  const int mode = RNA_enum_get(op->ptr, "mode");
1774 
1775  BezTriple *bezt;
1776  float refVal = 0.0f;
1777  bool keyExists;
1778  int i, match;
1779  bool first = true;
1780 
1781  /* skip if no keyframes to edit */
1782  if ((fcu->bezt == NULL) || (fcu->totvert < 2)) {
1783  return;
1784  }
1785 
1786  /* find the reference value from bones directly, which means that the user
1787  * doesn't need to firstly keyframe the pose (though this doesn't mean that
1788  * they can't either)
1789  */
1790  if (!pose_propagate_get_refVal(ob, fcu, &refVal)) {
1791  return;
1792  }
1793 
1794  /* find the first keyframe to start propagating from
1795  * - if there's a keyframe on the current frame, we probably want to save this value there too
1796  * since it may be as of yet unkeyed
1797  * - if starting before the starting frame, don't touch the key, as it may have had some valid
1798  * values
1799  * - if only doing selected keyframes, start from the first one
1800  */
1801  if (mode != POSE_PROPAGATE_SELECTED_KEYS) {
1802  match = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, startFrame, fcu->totvert, &keyExists);
1803 
1804  if (fcu->bezt[match].vec[1][0] < startFrame) {
1805  i = match + 1;
1806  }
1807  else {
1808  i = match;
1809  }
1810  }
1811  else {
1812  /* selected - start from first keyframe */
1813  i = 0;
1814  }
1815 
1816  for (bezt = &fcu->bezt[i]; i < fcu->totvert; i++, bezt++) {
1817  /* additional termination conditions based on the operator 'mode' property go here... */
1819  /* stop if keyframe is outside the accepted range */
1820  if (bezt->vec[1][0] > modeData.end_frame) {
1821  break;
1822  }
1823  }
1824  else if (mode == POSE_PROPAGATE_NEXT_KEY) {
1825  /* stop after the first keyframe has been processed */
1826  if (first == false) {
1827  break;
1828  }
1829  }
1830  else if (mode == POSE_PROPAGATE_LAST_KEY) {
1831  /* only affect this frame if it will be the last one */
1832  if (i != (fcu->totvert - 1)) {
1833  continue;
1834  }
1835  }
1836  else if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
1837  /* only allow if there's a marker on this frame */
1838  CfraElem *ce = NULL;
1839 
1840  /* stop on matching marker if there is one */
1841  for (ce = modeData.sel_markers.first; ce; ce = ce->next) {
1842  if (ce->cfra == round_fl_to_int(bezt->vec[1][0])) {
1843  break;
1844  }
1845  }
1846 
1847  /* skip this keyframe if no marker */
1848  if (ce == NULL) {
1849  continue;
1850  }
1851  }
1852  else if (mode == POSE_PROPAGATE_SELECTED_KEYS) {
1853  /* only allow if this keyframe is already selected - skip otherwise */
1854  if (BEZT_ISSEL_ANY(bezt) == 0) {
1855  continue;
1856  }
1857  }
1858 
1859  /* just flatten handles, since values will now be the same either side... */
1860  /* TODO: perhaps a fade-out modulation of the value is required here (optional once again)? */
1861  bezt->vec[0][1] = bezt->vec[1][1] = bezt->vec[2][1] = refVal;
1862 
1863  /* select keyframe to indicate that it's been changed */
1864  bezt->f2 |= SELECT;
1865  first = false;
1866  }
1867 }
1868 
1869 /* --------------------------------- */
1870 
1872 {
1874  ViewLayer *view_layer = CTX_data_view_layer(C);
1875  View3D *v3d = CTX_wm_view3d(C);
1876 
1877  ListBase pflinks = {NULL, NULL};
1878  tPChanFCurveLink *pfl;
1879 
1880  tPosePropagate_ModeData modeData;
1881  const int mode = RNA_enum_get(op->ptr, "mode");
1882 
1883  /* isolate F-Curves related to the selected bones */
1884  poseAnim_mapping_get(C, &pflinks);
1885 
1886  if (BLI_listbase_is_empty(&pflinks)) {
1887  /* There is a change the reason the list is empty is
1888  * that there is no valid object to propagate poses for.
1889  * This is very unlikely though, so we focus on the most likely issue. */
1890  BKE_report(op->reports, RPT_ERROR, "No keyframed poses to propagate to");
1891  return OPERATOR_CANCELLED;
1892  }
1893 
1894  /* mode-specific data preprocessing (requiring no access to curves) */
1895  if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
1896  /* get a list of selected markers */
1898  }
1899  else {
1900  /* assume everything else wants endFrame */
1901  modeData.end_frame = RNA_float_get(op->ptr, "end_frame");
1902  }
1903 
1904  /* for each bone, perform the copying required */
1905  for (pfl = pflinks.first; pfl; pfl = pfl->next) {
1906  LinkData *ld;
1907 
1908  /* mode-specific data preprocessing (requiring access to all curves) */
1909  if (mode == POSE_PROPAGATE_SMART_HOLDS) {
1910  /* we store in endFrame the end frame of the "long keyframe" (i.e. a held value) starting
1911  * from the keyframe that occurs after the current frame
1912  */
1913  modeData.end_frame = pose_propagate_get_boneHoldEndFrame(pfl, (float)CFRA);
1914  }
1915 
1916  /* go through propagating pose to keyframes, curve by curve */
1917  for (ld = pfl->fcurves.first; ld; ld = ld->next) {
1918  pose_propagate_fcurve(op, pfl->ob, (FCurve *)ld->data, (float)CFRA, modeData);
1919  }
1920  }
1921 
1922  /* free temp data */
1923  poseAnim_mapping_free(&pflinks);
1924 
1925  if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
1926  BLI_freelistN(&modeData.sel_markers);
1927  }
1928 
1929  /* updates + notifiers */
1930  FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
1932  }
1934 
1935  return OPERATOR_FINISHED;
1936 }
1937 
1938 /* --------------------------------- */
1939 
1941 {
1942  static const EnumPropertyItem terminate_items[] = {
1944  "WHILE_HELD",
1945  0,
1946  "While Held",
1947  "Propagate pose to all keyframes after current frame that don't change (Default behavior)"},
1949  "NEXT_KEY",
1950  0,
1951  "To Next Keyframe",
1952  "Propagate pose to first keyframe following the current frame only"},
1954  "LAST_KEY",
1955  0,
1956  "To Last Keyframe",
1957  "Propagate pose to the last keyframe only (i.e. making action cyclic)"},
1959  "BEFORE_FRAME",
1960  0,
1961  "Before Frame",
1962  "Propagate pose to all keyframes between current frame and 'Frame' property"},
1964  "BEFORE_END",
1965  0,
1966  "Before Last Keyframe",
1967  "Propagate pose to all keyframes from current frame until no more are found"},
1969  "SELECTED_KEYS",
1970  0,
1971  "On Selected Keyframes",
1972  "Propagate pose to all selected keyframes"},
1974  "SELECTED_MARKERS",
1975  0,
1976  "On Selected Markers",
1977  "Propagate pose to all keyframes occurring on frames with Scene Markers after the current "
1978  "frame"},
1979  {0, NULL, 0, NULL, NULL},
1980  };
1981 
1982  /* identifiers */
1983  ot->name = "Propagate Pose";
1984  ot->idname = "POSE_OT_propagate";
1985  ot->description =
1986  "Copy selected aspects of the current pose to subsequent poses already keyframed";
1987 
1988  /* callbacks */
1990  ot->poll = ED_operator_posemode; /* XXX: needs selected bones! */
1991 
1992  /* flag */
1994 
1995  /* properties */
1996  /* TODO: add "fade out" control for tapering off amount of propagation as time goes by? */
1997  ot->prop = RNA_def_enum(ot->srna,
1998  "mode",
1999  terminate_items,
2001  "Terminate Mode",
2002  "Method used to determine when to stop propagating pose to keyframes");
2004  "end_frame",
2005  250.0,
2006  FLT_MIN,
2007  FLT_MAX,
2008  "End Frame",
2009  "Frame to stop propagating frames to (for 'Before Frame' mode)",
2010  1.0,
2011  250.0);
2012 }
2013 
2014 /* **************************************************** */
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
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
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
float evaluate_fcurve(struct FCurve *fcu, float evaltime)
Definition: fcurve.c:2186
int BKE_fcurve_bezt_binarysearch_index(struct BezTriple array[], float frame, int arraylen, bool *r_replace)
Definition: fcurve.c:600
#define BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, v3d, r_len, mode)
Definition: BKE_layer.h:444
#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
@ NLATIME_CONVERT_UNMAP
Definition: BKE_nla.h:153
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode)
Definition: nla.c:582
General operations, lookup, etc. for blender objects.
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
@ B_UNIT_NONE
Definition: BKE_unit.h:78
#define BLI_assert(a)
Definition: BLI_assert.h:58
void BLI_dlrbTree_init(DLRBT_Tree *tree)
Definition: DLRB_tree.c:40
DLRBT_Node * BLI_dlrbTree_search_exact(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data)
Definition: DLRB_tree.c:177
void BLI_dlrbTree_free(DLRBT_Tree *tree)
Definition: DLRB_tree.c:66
DLRBT_Node * BLI_dlrbTree_search_next(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data)
Definition: DLRB_tree.c:256
DLRBT_Node * BLI_dlrbTree_search_prev(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data)
Definition: DLRB_tree.c:225
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
MINLINE int round_fl_to_int(float a)
float normalize_qt(float q[4])
float normalize_qt_qt(float r[4], const float q[4])
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], const float t)
void quat_to_compatible_quat(float q[4], const float a[4], const float old[4])
size_t size_t char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED(x)
#define ELEM(...)
#define TIP_(msgid)
@ ROT_MODE_AXISANGLE
@ POSE_BBONE_SHAPE
@ POSE_ROT
@ POSE_LOC
@ POSE_SIZE
@ POSE_LOCKED
@ POSE_DO_UNLOCK
#define BEZT_ISSEL_ANY(bezt)
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
@ OB_ARMATURE
#define MINAFRAME
#define CFRA
#define MAXFRAME
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
@ ACTKEYBLOCK_FLAG_STATIC_HOLD
void outputNumInput(NumInput *n, char *str, struct UnitSettings *unit_settings)
Definition: numinput.c:102
void initNumInput(NumInput *n)
Definition: numinput.c:83
#define NUM_STR_REP_LEN
Definition: ED_numinput.h:27
@ NUM_NO_NEGATIVE
Definition: ED_numinput.h:70
bool applyNumInput(NumInput *n, float *vec)
Definition: numinput.c:207
bool hasNumInput(const NumInput *n)
Definition: numinput.c:185
bool handleNumInput(struct bContext *C, NumInput *n, const struct wmEvent *event)
bool ED_operator_posemode(struct bContext *C)
Definition: screen_ops.c:484
void ED_area_status_text(ScrArea *area, const char *str)
Definition: area.c:815
Read Guarded memory(de)allocation.
Group RGB to Bright Vector Camera CLAMP
StructRNA RNA_PoseBone
@ PROP_FLOAT
Definition: RNA_types.h:75
@ PROP_BOOLEAN
Definition: RNA_types.h:73
@ PROP_ENUM
Definition: RNA_types.h:77
@ PROP_INT
Definition: RNA_types.h:74
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
#define C
Definition: RandGen.cpp:39
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:90
@ OPTYPE_BLOCKING
Definition: WM_types.h:157
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define KM_PRESS
Definition: WM_types.h:242
void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel)
Definition: anim_markers.c:330
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_autoKeyframe(struct bContext *C, struct Scene *scene, ListBase *pfLinks, float cframe)
Definition: pose_utils.c:272
void poseAnim_mapping_get(struct bContext *C, ListBase *pfLinks)
Definition: pose_utils.c:149
void poseAnim_mapping_refresh(struct bContext *C, struct Scene *scene, struct Object *ob)
struct Object * poseAnim_object_get(struct Object *ob_)
Definition: pose_utils.c:139
#define SELECT
Scene scene
short compare_ak_cfraPtr(void *node, void *data)
int actkeyblock_get_valid_hold(ActKeyColumn *ac)
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, int saction_flag)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
ePoseSlide_Modes
Definition: pose_slide.c:135
@ POSESLIDE_BREAKDOWN
Definition: pose_slide.c:138
@ POSESLIDE_PUSH
Definition: pose_slide.c:136
@ POSESLIDE_PUSH_REST
Definition: pose_slide.c:139
@ POSESLIDE_RELAX_REST
Definition: pose_slide.c:140
@ POSESLIDE_RELAX
Definition: pose_slide.c:137
static void pose_slide_toggle_channels_mode(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_Channels channel)
Definition: pose_slide.c:994
void POSE_OT_relax_rest(wmOperatorType *ot)
Definition: pose_slide.c:1513
static void pose_slide_exit(wmOperator *op)
Definition: pose_slide.c:265
static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
Definition: pose_slide.c:698
void POSE_OT_breakdown(wmOperatorType *ot)
Definition: pose_slide.c:1573
static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1298
static int pose_slide_relax_rest_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:1497
static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1358
static int pose_slide_relax_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1477
static const EnumPropertyItem prop_channels_types[]
Definition: pose_slide.c:157
union tPosePropagate_ModeData tPosePropagate_ModeData
static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1042
static void pose_slide_reset(tPoseSlideOp *pso)
Definition: pose_slide.c:781
static bool pose_propagate_get_refVal(Object *ob, FCurve *fcu, float *value)
Definition: pose_slide.c:1712
struct tPoseSlideOp tPoseSlideOp
static int pose_slide_push_rest_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:1437
ePoseSlide_AxisLock
Definition: pose_slide.c:172
@ PS_LOCK_Z
Definition: pose_slide.c:175
@ PS_LOCK_Y
Definition: pose_slide.c:174
@ PS_LOCK_X
Definition: pose_slide.c:173
static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *pso)
Definition: pose_slide.c:893
static const EnumPropertyItem prop_axis_lock_types[]
Definition: pose_slide.c:179
static bool pose_slide_toggle_axis_locks(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_AxisLock axis)
Definition: pose_slide.c:1015
static void pose_slide_draw_status(tPoseSlideOp *pso)
Definition: pose_slide.c:791
static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, float *val)
Definition: pose_slide.c:327
static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso)
Definition: pose_slide.c:1220
void POSE_OT_push_rest(wmOperatorType *ot)
Definition: pose_slide.c:1453
static void pose_slide_rest_pose_apply_other_rot(tPoseSlideOp *pso, float vec[4], bool quat)
Definition: pose_slide.c:619
struct tPoseSlideObject tPoseSlideObject
static void pose_slide_opdef_properties(wmOperatorType *ot)
Definition: pose_slide.c:1242
static void pose_slide_refresh(bContext *C, tPoseSlideOp *pso)
Definition: pose_slide.c:292
static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
Definition: pose_slide.c:504
static float pose_propagate_get_boneHoldEndFrame(tPChanFCurveLink *pfl, float startFrame)
Definition: pose_slide.c:1633
void POSE_OT_propagate(wmOperatorType *ot)
Definition: pose_slide.c:1940
static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso)
Definition: pose_slide.c:641
static bool pose_frame_range_from_object_get(tPoseSlideOp *pso, Object *ob, float *prevFrameF, float *nextFrameF)
Definition: pose_slide.c:307
static void pose_slide_autoKeyframe(bContext *C, tPoseSlideOp *pso)
Definition: pose_slide.c:774
static int pose_slide_breakdown_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:1557
static int pose_slide_push_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1417
static int pose_slide_push_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:1318
static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu, float startFrame, tPosePropagate_ModeData modeData)
Definition: pose_slide.c:1770
static int pose_propagate_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:1871
static void pose_slide_mouse_update_percentage(tPoseSlideOp *pso, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:985
static void pose_slide_cancel(bContext *UNUSED(C), wmOperator *op)
Definition: pose_slide.c:1213
void POSE_OT_relax(wmOperatorType *ot)
Definition: pose_slide.c:1394
static void pose_slide_apply_vec3(tPoseSlideOp *pso, tPChanFCurveLink *pfl, float vec[3], const char propName[])
Definition: pose_slide.c:393
ePoseSlide_Channels
Definition: pose_slide.c:144
@ PS_TFM_SIZE
Definition: pose_slide.c:149
@ PS_TFM_LOC
Definition: pose_slide.c:147
@ PS_TFM_PROPS
Definition: pose_slide.c:153
@ PS_TFM_ALL
Definition: pose_slide.c:145
@ PS_TFM_BBONE_SHAPE
Definition: pose_slide.c:151
@ PS_TFM_ROT
Definition: pose_slide.c:148
static int pose_slide_relax_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:1378
void POSE_OT_push(wmOperatorType *ot)
Definition: pose_slide.c:1334
static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode)
Definition: pose_slide.c:191
static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1537
static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], float default_value)
Definition: pose_slide.c:600
ePosePropagate_Termination
Definition: pose_slide.c:1598
@ POSE_PROPAGATE_LAST_KEY
Definition: pose_slide.c:1602
@ POSE_PROPAGATE_BEFORE_FRAME
Definition: pose_slide.c:1606
@ POSE_PROPAGATE_SELECTED_MARKERS
Definition: pose_slide.c:1613
@ POSE_PROPAGATE_BEFORE_END
Definition: pose_slide.c:1608
@ POSE_PROPAGATE_SMART_HOLDS
Definition: pose_slide.c:1600
@ POSE_PROPAGATE_NEXT_KEY
Definition: pose_slide.c:1604
@ POSE_PROPAGATE_SELECTED_KEYS
Definition: pose_slide.c:1611
static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl, const char prop_prefix[])
Definition: pose_slide.c:425
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2941
void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
Definition: rna_access.c:2627
bool RNA_property_array_check(PropertyRNA *prop)
Definition: rna_access.c:1223
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:122
int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:2759
float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:3108
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1155
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6319
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:866
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2331
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2607
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
Definition: rna_access.c:2358
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6355
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:6366
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1218
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3543
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
Definition: rna_access.c:2964
bool RNA_path_resolve_property(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition: rna_access.c:5434
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6413
bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:2453
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3825
PropertyRNA * RNA_def_float_factor(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:4133
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3585
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
struct ActKeyColumn * next
struct ActKeyColumn * prev
float vec[3][3]
float cfra
Definition: BKE_fcurve.h:56
struct CfraElem * next
Definition: BKE_fcurve.h:55
void * root
Definition: BLI_dlrbTree.h:69
char * rna_path
BezTriple * bezt
int array_index
unsigned int totvert
void * data
Definition: DNA_listBase.h:42
struct LinkData * next
Definition: DNA_listBase.h:41
void * first
Definition: DNA_listBase.h:47
short idx_max
Definition: ED_numinput.h:34
short val_flag[NUM_MAX_ELEMENTS]
Definition: ED_numinput.h:43
int unit_type[NUM_MAX_ELEMENTS]
Definition: ED_numinput.h:37
struct bPose * pose
struct AnimData * adt
struct RenderData r
struct UnitSettings unit
ListBase markers
short flag
int xmin
Definition: DNA_vec_types.h:79
NumInput num
Definition: pose_slide.c:122
ARegion * region
Definition: pose_slide.c:91
float percentage
Definition: pose_slide.c:119
ScrArea * area
Definition: pose_slide.c:89
struct tPoseSlideObject * ob_data_array
Definition: pose_slide.c:124
DLRBT_Tree keys
Definition: pose_slide.c:98
short channels
Definition: pose_slide.c:114
short axislock
Definition: pose_slide.c:116
ListBase pfLinks
Definition: pose_slide.c:96
Scene * scene
Definition: pose_slide.c:87
uint objects_len
Definition: pose_slide.c:93
short val
Definition: WM_types.h:579
short type
Definition: WM_types.h:577
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
struct PointerRNA * ptr
uint len
void WM_cursor_modal_set(wmWindow *win, int val)
Definition: wm_cursors.c:207
void WM_cursor_modal_restore(wmWindow *win)
Definition: wm_cursors.c:216
@ WM_CURSOR_EW_SCROLL
Definition: wm_cursors.h:69
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
@ RIGHTMOUSE
@ EVT_YKEY
@ EVT_SKEY
@ EVT_XKEY
@ EVT_CKEY
@ EVT_GKEY
@ EVT_PADENTER
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_ZKEY
@ EVT_ESCKEY
@ EVT_RKEY
@ EVT_BKEY
@ EVT_RETKEY
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156