Blender  V3.3
pose_slide.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2009 Blender Foundation, Joshua Leung. */
3 
30 #include "MEM_guardedalloc.h"
31 
32 #include "BLI_blenlib.h"
33 #include "BLI_dlrbTree.h"
34 #include "BLI_math.h"
35 
36 #include "BLT_translation.h"
37 
38 #include "DNA_anim_types.h"
39 #include "DNA_armature_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_vec_types.h"
43 
44 #include "BKE_fcurve.h"
45 #include "BKE_nla.h"
46 
47 #include "BKE_context.h"
48 #include "BKE_layer.h"
49 #include "BKE_object.h"
50 #include "BKE_report.h"
51 #include "BKE_screen.h"
52 #include "BKE_unit.h"
53 
54 #include "RNA_access.h"
55 #include "RNA_define.h"
56 #include "RNA_path.h"
57 #include "RNA_prototypes.h"
58 
59 #include "WM_api.h"
60 #include "WM_types.h"
61 
62 #include "UI_interface.h"
63 #include "UI_resources.h"
64 
65 #include "ED_armature.h"
66 #include "ED_keyframes_keylist.h"
67 #include "ED_markers.h"
68 #include "ED_numinput.h"
69 #include "ED_screen.h"
70 #include "ED_space_api.h"
71 #include "ED_util.h"
72 
73 #include "GPU_immediate.h"
74 #include "GPU_immediate_util.h"
75 #include "GPU_matrix.h"
76 #include "GPU_state.h"
77 
78 #include "armature_intern.h"
79 
80 #include "BLF_api.h"
81 
82 /* Pixel distance from 0% to 100%. */
83 #define SLIDE_PIXEL_DISTANCE (300 * U.pixelsize)
84 #define OVERSHOOT_RANGE_DELTA 0.2f
85 
86 /* **************************************************** */
87 /* A) Push & Relax, Breakdowner */
88 
90 typedef enum ePoseSlide_AxisLock {
91  PS_LOCK_X = (1 << 0),
92  PS_LOCK_Y = (1 << 1),
93  PS_LOCK_Z = (1 << 2),
95 
97 typedef enum ePoseSlide_Modes {
108 
110 typedef enum ePoseSlide_Channels {
111  PS_TFM_ALL = 0, /* All transforms and properties */
112 
113  PS_TFM_LOC, /* Loc/Rot/Scale */
116 
117  PS_TFM_BBONE_SHAPE, /* Bendy Bones */
118 
119  PS_TFM_PROPS, /* Custom Properties */
121 
123 typedef struct tPoseSlideOp {
132 
137 
139  int cframe;
140 
145 
149  short flag;
150 
151  /* Store overlay settings when invoking the operator. Bones will be temporarily hidden. */
153 
158 
159  struct tSlider *slider;
160 
163 
166 
167 typedef struct tPoseSlideObject {
171  float prevFrameF;
173  float nextFrameF;
174  bool valid;
176 
179  {PS_TFM_ALL,
180  "ALL",
181  0,
182  "All Properties",
183  "All properties, including transforms, bendy bone shape, and custom properties"},
184  {PS_TFM_LOC, "LOC", 0, "Location", "Location only"},
185  {PS_TFM_ROT, "ROT", 0, "Rotation", "Rotation only"},
186  {PS_TFM_SIZE, "SIZE", 0, "Scale", "Scale only"},
187  {PS_TFM_BBONE_SHAPE, "BBONE", 0, "Bendy Bone", "Bendy Bone shape properties"},
188  {PS_TFM_PROPS, "CUSTOM", 0, "Custom Properties", "Custom properties"},
189  {0, NULL, 0, NULL, NULL},
190 };
191 
192 /* Property enum for ePoseSlide_AxisLock */
194  {0, "FREE", 0, "Free", "All axes are affected"},
195  {PS_LOCK_X, "X", 0, "X", "Only X-axis transforms are affected"},
196  {PS_LOCK_Y, "Y", 0, "Y", "Only Y-axis transforms are affected"},
197  {PS_LOCK_Z, "Z", 0, "Z", "Only Z-axis transforms are affected"},
198  /* TODO: Combinations? */
199  {0, NULL, 0, NULL, NULL},
200 };
201 
202 /* ------------------------------------ */
203 
206 {
207  tPoseSlideOp *pso;
208 
209  /* Init slide-op data. */
210  pso = op->customdata = MEM_callocN(sizeof(tPoseSlideOp), "tPoseSlideOp");
211 
212  /* Get info from context. */
213  pso->scene = CTX_data_scene(C);
214  pso->area = CTX_wm_area(C); /* Only really needed when doing modal(). */
215  pso->region = CTX_wm_region(C); /* Only really needed when doing modal(). */
216 
217  pso->cframe = pso->scene->r.cfra;
218  pso->mode = mode;
219 
220  /* Set range info from property values - these may get overridden for the invoke(). */
221  pso->prevFrame = RNA_int_get(op->ptr, "prev_frame");
222  pso->nextFrame = RNA_int_get(op->ptr, "next_frame");
223 
224  /* Get the set of properties/axes that can be operated on. */
225  pso->channels = RNA_enum_get(op->ptr, "channels");
226  pso->axislock = RNA_enum_get(op->ptr, "axis_lock");
227 
228  pso->slider = ED_slider_create(C);
229  ED_slider_factor_set(pso->slider, RNA_float_get(op->ptr, "factor"));
230 
231  /* For each Pose-Channel which gets affected, get the F-Curves for that channel
232  * and set the relevant transform flags. */
234 
238  "pose slide objects data");
239 
240  for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
241  tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
242  Object *ob_iter = poseAnim_object_get(objects[ob_index]);
243 
244  /* Ensure validity of the settings from the context. */
245  if (ob_iter == NULL) {
246  continue;
247  }
248 
249  ob_data->ob = ob_iter;
250  ob_data->valid = true;
251 
252  /* Apply NLA mapping corrections so the frame look-ups work. */
254  ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
256  ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
257 
258  /* Set depsgraph flags. */
259  /* Make sure the lock is set OK, unlock can be accidentally saved? */
260  ob_data->ob->pose->flag |= POSE_LOCKED;
261  ob_data->ob->pose->flag &= ~POSE_DO_UNLOCK;
262  }
263  MEM_freeN(objects);
264 
265  /* Do basic initialize of RB-BST used for finding keyframes, but leave the filling of it up
266  * to the caller of this (usually only invoke() will do it, to make things more efficient). */
267  pso->keylist = ED_keylist_create();
268 
269  /* Initialize numeric input. */
270  initNumInput(&pso->num);
271  pso->num.idx_max = 0; /* One axis. */
272  pso->num.val_flag[0] |= NUM_NO_NEGATIVE;
273  pso->num.unit_type[0] = B_UNIT_NONE; /* Percentages don't have any units. */
274 
275  /* Return status is whether we've got all the data we were requested to get. */
276  return 1;
277 }
278 
283 {
284  tPoseSlideOp *pso = op->customdata;
285 
286  ED_slider_destroy(C, pso->slider);
287 
288  /* Hide Bone Overlay. */
289  if (pso->area) {
290  View3D *v3d = pso->area->spacedata.first;
291  v3d->overlay.flag = pso->overlay_flag;
292  }
293 
294  /* Free the temp pchan links and their data. */
296 
297  /* Free RB-BST for keyframes (if it contained data). */
298  ED_keylist_free(pso->keylist);
299 
300  if (pso->ob_data_array != NULL) {
301  MEM_freeN(pso->ob_data_array);
302  }
303 
304  /* Free data itself. */
305  MEM_freeN(pso);
306 
307  /* Cleanup. */
308  op->customdata = NULL;
309 }
310 
311 /* ------------------------------------ */
312 
317 {
318  /* Wrapper around the generic version, allowing us to add some custom stuff later still. */
319  for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
320  tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
321  if (ob_data->valid) {
322  poseAnim_mapping_refresh(C, pso->scene, ob_data->ob);
323  }
324  }
325 }
326 
332  Object *ob,
333  float *prevFrameF,
334  float *nextFrameF)
335 {
336  for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
337  tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
338  Object *ob_iter = ob_data->ob;
339 
340  if (ob_iter == ob) {
341  *prevFrameF = ob_data->prevFrameF;
342  *nextFrameF = ob_data->nextFrameF;
343  return true;
344  }
345  }
346  *prevFrameF = *nextFrameF = 0.0f;
347  return false;
348 }
349 
353 static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, float *val)
354 {
355  float prevFrameF, nextFrameF;
356  float cframe = (float)pso->cframe;
357  float sVal, eVal;
358  float w1, w2;
359 
360  pose_frame_range_from_object_get(pso, ob, &prevFrameF, &nextFrameF);
361 
362  /* Get keyframe values for endpoint poses to blend with. */
363  /* Previous/start. */
364  sVal = evaluate_fcurve(fcu, prevFrameF);
365  /* Next/end. */
366  eVal = evaluate_fcurve(fcu, nextFrameF);
367 
368  /* Calculate the relative weights of the endpoints. */
369  if (pso->mode == POSESLIDE_BREAKDOWN) {
370  /* Get weights from the factor control. */
371  w1 = ED_slider_factor_get(pso->slider); /* This must come second. */
372  w2 = 1.0f - w1; /* This must come first. */
373  }
374  else {
375  /* - these weights are derived from the relative distance of these
376  * poses from the current frame
377  * - they then get normalized so that they only sum up to 1
378  */
379  float wtot;
380 
381  w1 = cframe - (float)pso->prevFrame;
382  w2 = (float)pso->nextFrame - cframe;
383 
384  wtot = w1 + w2;
385  w1 = (w1 / wtot);
386  w2 = (w2 / wtot);
387  }
388 
389  /* Depending on the mode, calculate the new value:
390  * - In all of these, the start+end values are multiplied by w2 and w1 (respectively),
391  * since multiplication in another order would decrease
392  * the value the current frame is closer to.
393  */
394  switch (pso->mode) {
395  case POSESLIDE_PUSH: /* Make the current pose more pronounced. */
396  {
397  /* Slide the pose away from the breakdown pose in the timeline */
398  (*val) -= ((sVal * w2) + (eVal * w1) - (*val)) * ED_slider_factor_get(pso->slider);
399  break;
400  }
401  case POSESLIDE_RELAX: /* Make the current pose more like its surrounding ones. */
402  {
403  /* Slide the pose towards the breakdown pose in the timeline */
404  (*val) += ((sVal * w2) + (eVal * w1) - (*val)) * ED_slider_factor_get(pso->slider);
405  break;
406  }
407  case POSESLIDE_BREAKDOWN: /* Make the current pose slide around between the endpoints. */
408  {
409  /* Perform simple linear interpolation -
410  * coefficient for start must come from pso->factor. */
411  /* TODO: make this use some kind of spline interpolation instead? */
412  (*val) = ((sVal * w2) + (eVal * w1));
413  break;
414  }
415  case POSESLIDE_BLEND: /* Blend the current pose with the previous (<50%) or next key (>50%). */
416  {
417  /* FCurve value on current frame. */
418  const float cVal = evaluate_fcurve(fcu, cframe);
419  const float factor = ED_slider_factor_get(pso->slider);
420  /* Convert factor to absolute 0-1 range. */
421  const float blend_factor = fabs((factor - 0.5f) * 2);
422 
423  if (factor < 0.5) {
424  /* Blend to previous key. */
425  (*val) = (cVal * (1 - blend_factor)) + (sVal * blend_factor);
426  }
427  else {
428  /* Blend to next key. */
429  (*val) = (cVal * (1 - blend_factor)) + (eVal * blend_factor);
430  }
431 
432  break;
433  }
434  /* Those are handled in pose_slide_rest_pose_apply. */
435  case POSESLIDE_PUSH_REST:
436  case POSESLIDE_RELAX_REST: {
437  break;
438  }
439  }
440 }
441 
446  tPChanFCurveLink *pfl,
447  float vec[3],
448  const char propName[])
449 {
450  LinkData *ld = NULL;
451  char *path = NULL;
452 
453  /* Get the path to use. */
454  path = BLI_sprintfN("%s.%s", pfl->pchan_path, propName);
455 
456  /* Using this path, find each matching F-Curve for the variables we're interested in. */
457  while ((ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path))) {
458  FCurve *fcu = (FCurve *)ld->data;
459  const int idx = fcu->array_index;
460  const int lock = pso->axislock;
461 
462  /* Check if this F-Curve is ok given the current axis locks. */
463  BLI_assert(fcu->array_index < 3);
464 
465  if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) ||
466  ((lock & PS_LOCK_Z) && (idx == 2))) {
467  /* Just work on these channels one by one... there's no interaction between values. */
468  pose_slide_apply_val(pso, fcu, pfl->ob, &vec[fcu->array_index]);
469  }
470  }
471 
472  /* Free the temp path we got. */
473  MEM_freeN(path);
474 }
475 
480  tPChanFCurveLink *pfl,
481  const char prop_prefix[])
482 {
483  PointerRNA ptr = {NULL};
484  LinkData *ld;
485  int len = strlen(pfl->pchan_path);
486 
487  /* Setup pointer RNA for resolving paths. */
488  RNA_pointer_create(NULL, &RNA_PoseBone, pfl->pchan, &ptr);
489 
490  /* - custom properties are just denoted using ["..."][etc.] after the end of the base path,
491  * so just check for opening pair after the end of the path
492  * - bbone properties are similar, but they always start with a prefix "bbone_*",
493  * so a similar method should work here for those too
494  */
495  for (ld = pfl->fcurves.first; ld; ld = ld->next) {
496  FCurve *fcu = (FCurve *)ld->data;
497  const char *bPtr, *pPtr;
498 
499  if (fcu->rna_path == NULL) {
500  continue;
501  }
502 
503  /* Do we have a match?
504  * - bPtr is the RNA Path with the standard part chopped off.
505  * - pPtr is the chunk of the path which is left over.
506  */
507  bPtr = strstr(fcu->rna_path, pfl->pchan_path) + len;
508  pPtr = strstr(bPtr, prop_prefix);
509 
510  if (pPtr) {
511  /* Use RNA to try and get a handle on this property, then, assuming that it is just
512  * numerical, try and grab the value as a float for temp editing before setting back. */
513  PropertyRNA *prop = RNA_struct_find_property(&ptr, pPtr);
514 
515  if (prop) {
516  switch (RNA_property_type(prop)) {
517  /* Continuous values that can be smoothly interpolated. */
518  case PROP_FLOAT: {
519  float tval = RNA_property_float_get(&ptr, prop);
520  pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
521  RNA_property_float_set(&ptr, prop, tval);
522  break;
523  }
524  case PROP_INT: {
525  float tval = (float)RNA_property_int_get(&ptr, prop);
526  pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
527  RNA_property_int_set(&ptr, prop, (int)tval);
528  break;
529  }
530 
531  /* Values which can only take discrete values. */
532  case PROP_BOOLEAN: {
533  float tval = (float)RNA_property_boolean_get(&ptr, prop);
534  pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
536  &ptr, prop, (int)tval); /* XXX: do we need threshold clamping here? */
537  break;
538  }
539  case PROP_ENUM: {
540  /* Don't handle this case - these don't usually represent interchangeable
541  * set of values which should be interpolated between. */
542  break;
543  }
544 
545  default:
546  /* Cannot handle. */
547  // printf("Cannot Pose Slide non-numerical property\n");
548  break;
549  }
550  }
551  }
552  }
553 }
554 
559 {
560  FCurve *fcu_w = NULL, *fcu_x = NULL, *fcu_y = NULL, *fcu_z = NULL;
561  bPoseChannel *pchan = pfl->pchan;
562  LinkData *ld = NULL;
563  char *path = NULL;
564  float cframe;
565  float prevFrameF, nextFrameF;
566 
567  if (!pose_frame_range_from_object_get(pso, pfl->ob, &prevFrameF, &nextFrameF)) {
568  BLI_assert_msg(0, "Invalid pfl data");
569  return;
570  }
571 
572  /* Get the path to use - this should be quaternion rotations only (needs care). */
573  path = BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation_quaternion");
574 
575  /* Get the current frame number. */
576  cframe = (float)pso->cframe;
577 
578  /* Using this path, find each matching F-Curve for the variables we're interested in. */
579  while ((ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path))) {
580  FCurve *fcu = (FCurve *)ld->data;
581 
582  /* Assign this F-Curve to one of the relevant pointers. */
583  switch (fcu->array_index) {
584  case 3: /* z */
585  fcu_z = fcu;
586  break;
587  case 2: /* y */
588  fcu_y = fcu;
589  break;
590  case 1: /* x */
591  fcu_x = fcu;
592  break;
593  case 0: /* w */
594  fcu_w = fcu;
595  break;
596  }
597  }
598 
599  /* Only if all channels exist, proceed. */
600  if (fcu_w && fcu_x && fcu_y && fcu_z) {
601  float quat_final[4];
602 
603  /* Perform blending. */
605  float quat_prev[4], quat_next[4];
606 
607  quat_prev[0] = evaluate_fcurve(fcu_w, prevFrameF);
608  quat_prev[1] = evaluate_fcurve(fcu_x, prevFrameF);
609  quat_prev[2] = evaluate_fcurve(fcu_y, prevFrameF);
610  quat_prev[3] = evaluate_fcurve(fcu_z, prevFrameF);
611 
612  quat_next[0] = evaluate_fcurve(fcu_w, nextFrameF);
613  quat_next[1] = evaluate_fcurve(fcu_x, nextFrameF);
614  quat_next[2] = evaluate_fcurve(fcu_y, nextFrameF);
615  quat_next[3] = evaluate_fcurve(fcu_z, nextFrameF);
616 
617  normalize_qt(quat_prev);
618  normalize_qt(quat_next);
619 
620  if (pso->mode == POSESLIDE_BREAKDOWN) {
621  /* Just perform the interpolation between quat_prev and
622  * quat_next using pso->factor as a guide. */
623  interp_qt_qtqt(quat_final, quat_prev, quat_next, ED_slider_factor_get(pso->slider));
624  }
625  else {
626  float quat_curr[4], quat_breakdown[4];
627 
628  normalize_qt_qt(quat_curr, pchan->quat);
629 
630  /* Compute breakdown based on actual frame range. */
631  const float factor = (cframe - pso->prevFrame) / (float)(pso->nextFrame - pso->prevFrame);
632 
633  interp_qt_qtqt(quat_breakdown, quat_prev, quat_next, factor);
634 
635  if (pso->mode == POSESLIDE_PUSH) {
637  quat_final, quat_breakdown, quat_curr, 1.0f + ED_slider_factor_get(pso->slider));
638  }
639  else {
641  interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, ED_slider_factor_get(pso->slider));
642  }
643  }
644  }
645  else if (pso->mode == POSESLIDE_BLEND) {
646  float quat_blend[4];
647  float quat_curr[4];
648 
649  copy_qt_qt(quat_curr, pchan->quat);
650 
651  if (ED_slider_factor_get(pso->slider) < 0.5) {
652  quat_blend[0] = evaluate_fcurve(fcu_w, prevFrameF);
653  quat_blend[1] = evaluate_fcurve(fcu_x, prevFrameF);
654  quat_blend[2] = evaluate_fcurve(fcu_y, prevFrameF);
655  quat_blend[3] = evaluate_fcurve(fcu_z, prevFrameF);
656  }
657  else {
658  quat_blend[0] = evaluate_fcurve(fcu_w, nextFrameF);
659  quat_blend[1] = evaluate_fcurve(fcu_x, nextFrameF);
660  quat_blend[2] = evaluate_fcurve(fcu_y, nextFrameF);
661  quat_blend[3] = evaluate_fcurve(fcu_z, nextFrameF);
662  }
663 
664  normalize_qt(quat_blend);
665  normalize_qt(quat_curr);
666 
667  const float blend_factor = fabs((ED_slider_factor_get(pso->slider) - 0.5f) * 2);
668 
669  interp_qt_qtqt(quat_final, quat_curr, quat_blend, blend_factor);
670  }
671 
672  /* Apply final to the pose bone, keeping compatible for similar keyframe positions. */
673  quat_to_compatible_quat(pchan->quat, quat_final, pchan->quat);
674  }
675 
676  /* Free the path now. */
677  MEM_freeN(path);
678 }
679 
680 static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], float default_value)
681 {
682  /* We only slide to the rest pose. So only use the default rest pose value. */
683  const int lock = pso->axislock;
684  for (int idx = 0; idx < 3; idx++) {
685  if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) ||
686  ((lock & PS_LOCK_Z) && (idx == 2))) {
687  float diff_val = default_value - vec[idx];
688  if (pso->mode == POSESLIDE_RELAX_REST) {
689  vec[idx] += ED_slider_factor_get(pso->slider) * diff_val;
690  }
691  else {
692  /* Push */
693  vec[idx] -= ED_slider_factor_get(pso->slider) * diff_val;
694  }
695  }
696  }
697 }
698 
699 static void pose_slide_rest_pose_apply_other_rot(tPoseSlideOp *pso, float vec[4], bool quat)
700 {
701  /* We only slide to the rest pose. So only use the default rest pose value. */
702  float default_values[] = {1.0f, 0.0f, 0.0f, 0.0f};
703  if (!quat) {
704  /* Axis Angle */
705  default_values[0] = 0.0f;
706  default_values[2] = 1.0f;
707  }
708  for (int idx = 0; idx < 4; idx++) {
709  float diff_val = default_values[idx] - vec[idx];
710  if (pso->mode == POSESLIDE_RELAX_REST) {
711  vec[idx] += ED_slider_factor_get(pso->slider) * diff_val;
712  }
713  else {
714  /* Push */
715  vec[idx] -= ED_slider_factor_get(pso->slider) * diff_val;
716  }
717  }
718 }
719 
724 {
725  tPChanFCurveLink *pfl;
726 
727  /* For each link, handle each set of transforms. */
728  for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
729  /* Valid transforms for each #bPoseChannel should have been noted already.
730  * - Sliding the pose should be a straightforward exercise for location+rotation,
731  * but rotations get more complicated since we may want to use quaternion blending
732  * for quaternions instead.
733  */
734  bPoseChannel *pchan = pfl->pchan;
735 
736  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) {
737  /* Calculate these for the 'location' vector, and use location curves. */
738  pose_slide_rest_pose_apply_vec3(pso, pchan->loc, 0.0f);
739  }
740 
741  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) {
742  /* Calculate these for the 'scale' vector, and use scale curves. */
743  pose_slide_rest_pose_apply_vec3(pso, pchan->size, 1.0f);
744  }
745 
746  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) {
747  /* Everything depends on the rotation mode. */
748  if (pchan->rotmode > 0) {
749  /* Eulers - so calculate these for the 'eul' vector, and use euler_rotation curves. */
750  pose_slide_rest_pose_apply_vec3(pso, pchan->eul, 0.0f);
751  }
752  else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
753  pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, false);
754  }
755  else {
756  /* Quaternions - use quaternion blending. */
757  pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, true);
758  }
759  }
760 
761  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) {
762  /* Bbone properties - they all start a "bbone_" prefix. */
763  /* TODO: Not implemented. */
764  // pose_slide_apply_props(pso, pfl, "bbone_");
765  }
766 
767  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
768  /* Not strictly a transform, but custom properties contribute
769  * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */
770  /* TODO: Not implemented. */
771  // pose_slide_apply_props(pso, pfl, "[\"");
772  }
773  }
774 
775  /* Depsgraph updates + redraws. */
776  pose_slide_refresh(C, pso);
777 }
778 
783 {
784  tPChanFCurveLink *pfl;
785 
786  /* Sanitize the frame ranges. */
787  if (pso->prevFrame == pso->nextFrame) {
788  /* Move out one step either side. */
789  pso->prevFrame--;
790  pso->nextFrame++;
791 
792  for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
793  tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
794 
795  if (!ob_data->valid) {
796  continue;
797  }
798 
799  /* Apply NLA mapping corrections so the frame look-ups work. */
801  ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
803  ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
804  }
805  }
806 
807  /* For each link, handle each set of transforms. */
808  for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
809  /* Valid transforms for each #bPoseChannel should have been noted already
810  * - sliding the pose should be a straightforward exercise for location+rotation,
811  * but rotations get more complicated since we may want to use quaternion blending
812  * for quaternions instead...
813  */
814  bPoseChannel *pchan = pfl->pchan;
815 
816  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) {
817  /* Calculate these for the 'location' vector, and use location curves. */
818  pose_slide_apply_vec3(pso, pfl, pchan->loc, "location");
819  }
820 
821  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) {
822  /* Calculate these for the 'scale' vector, and use scale curves. */
823  pose_slide_apply_vec3(pso, pfl, pchan->size, "scale");
824  }
825 
826  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) {
827  /* Everything depends on the rotation mode. */
828  if (pchan->rotmode > 0) {
829  /* Eulers - so calculate these for the 'eul' vector, and use euler_rotation curves. */
830  pose_slide_apply_vec3(pso, pfl, pchan->eul, "rotation_euler");
831  }
832  else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
833  /* TODO: need to figure out how to do this! */
834  }
835  else {
836  /* Quaternions - use quaternion blending. */
837  pose_slide_apply_quat(pso, pfl);
838  }
839  }
840 
841  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) {
842  /* Bbone properties - they all start a "bbone_" prefix. */
843  pose_slide_apply_props(pso, pfl, "bbone_");
844  }
845 
846  if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
847  /* Not strictly a transform, but custom properties contribute
848  * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */
849  pose_slide_apply_props(pso, pfl, "[\"");
850  }
851  }
852 
853  /* Depsgraph updates + redraws. */
854  pose_slide_refresh(C, pso);
855 }
856 
861 {
862  /* Wrapper around the generic call. */
863  poseAnim_mapping_autoKeyframe(C, pso->scene, &pso->pfLinks, (float)pso->cframe);
864 }
865 
870 {
871  /* Wrapper around the generic call, so that custom stuff can be added later. */
873 }
874 
875 /* ------------------------------------ */
876 
883 {
884  char status_str[UI_MAX_DRAW_STR];
885  char limits_str[UI_MAX_DRAW_STR];
886  char axis_str[50];
887  char mode_str[32];
888  char slider_str[UI_MAX_DRAW_STR];
889  char bone_vis_str[50];
890 
891  switch (pso->mode) {
892  case POSESLIDE_PUSH:
893  strcpy(mode_str, TIP_("Push Pose"));
894  break;
895  case POSESLIDE_RELAX:
896  strcpy(mode_str, TIP_("Relax Pose"));
897  break;
898  case POSESLIDE_BREAKDOWN:
899  strcpy(mode_str, TIP_("Breakdown"));
900  break;
901  case POSESLIDE_BLEND:
902  strcpy(mode_str, TIP_("Blend to Neighbor"));
903  break;
904 
905  default:
906  /* Unknown. */
907  strcpy(mode_str, TIP_("Sliding-Tool"));
908  break;
909  }
910 
911  switch (pso->axislock) {
912  case PS_LOCK_X:
913  STRNCPY(axis_str, TIP_("[X]/Y/Z axis only (X to clear)"));
914  break;
915  case PS_LOCK_Y:
916  STRNCPY(axis_str, TIP_("X/[Y]/Z axis only (Y to clear)"));
917  break;
918  case PS_LOCK_Z:
919  STRNCPY(axis_str, TIP_("X/Y/[Z] axis only (Z to clear)"));
920  break;
921 
922  default:
924  STRNCPY(axis_str, TIP_("X/Y/Z = Axis Constraint"));
925  }
926  else {
927  axis_str[0] = '\0';
928  }
929  break;
930  }
931 
932  switch (pso->channels) {
933  case PS_TFM_LOC:
934  BLI_snprintf(limits_str,
935  sizeof(limits_str),
936  TIP_("[G]/R/S/B/C - Location only (G to clear) | %s"),
937  axis_str);
938  break;
939  case PS_TFM_ROT:
940  BLI_snprintf(limits_str,
941  sizeof(limits_str),
942  TIP_("G/[R]/S/B/C - Rotation only (R to clear) | %s"),
943  axis_str);
944  break;
945  case PS_TFM_SIZE:
946  BLI_snprintf(limits_str,
947  sizeof(limits_str),
948  TIP_("G/R/[S]/B/C - Scale only (S to clear) | %s"),
949  axis_str);
950  break;
951  case PS_TFM_BBONE_SHAPE:
952  STRNCPY(limits_str, TIP_("G/R/S/[B]/C - Bendy Bone properties only (B to clear) | %s"));
953  break;
954  case PS_TFM_PROPS:
955  STRNCPY(limits_str, TIP_("G/R/S/B/[C] - Custom Properties only (C to clear) | %s"));
956  break;
957  default:
958  STRNCPY(limits_str, TIP_("G/R/S/B/C - Limit to Transform/Property Set"));
959  break;
960  }
961 
962  STRNCPY(bone_vis_str, TIP_("[H] - Toggle bone visibility"));
963 
964  ED_slider_status_string_get(pso->slider, slider_str, sizeof(slider_str));
965 
966  if (hasNumInput(&pso->num)) {
967  Scene *scene = pso->scene;
968  char str_offs[NUM_STR_REP_LEN];
969 
970  outputNumInput(&pso->num, str_offs, &scene->unit);
971 
972  BLI_snprintf(status_str, sizeof(status_str), "%s: %s | %s", mode_str, str_offs, limits_str);
973  }
974  else {
975  BLI_snprintf(status_str,
976  sizeof(status_str),
977  "%s: %s | %s | %s",
978  mode_str,
979  limits_str,
980  slider_str,
981  bone_vis_str);
982  }
983 
984  ED_workspace_status_text(C, status_str);
985  ED_area_status_text(pso->area, "");
986 }
987 
991 static int pose_slide_invoke_common(bContext *C, wmOperator *op, const wmEvent *event)
992 {
993  tPChanFCurveLink *pfl;
994  wmWindow *win = CTX_wm_window(C);
995 
996  tPoseSlideOp *pso = op->customdata;
997 
998  ED_slider_init(pso->slider, event);
999 
1000  /* For each link, add all its keyframes to the search tree. */
1001  for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
1002  LinkData *ld;
1003 
1004  /* Do this for each F-Curve. */
1005  for (ld = pfl->fcurves.first; ld; ld = ld->next) {
1006  FCurve *fcu = (FCurve *)ld->data;
1007  fcurve_to_keylist(pfl->ob->adt, fcu, pso->keylist, 0);
1008  }
1009  }
1010 
1011  /* Cancel if no keyframes found. */
1013  if (ED_keylist_is_empty(pso->keylist)) {
1014  BKE_report(op->reports, RPT_ERROR, "No keyframes to slide between");
1015  pose_slide_exit(C, op);
1016  return OPERATOR_CANCELLED;
1017  }
1018 
1019  float cframe = (float)pso->cframe;
1020 
1021  /* Firstly, check if the current frame is a keyframe. */
1022  const ActKeyColumn *ak = ED_keylist_find_exact(pso->keylist, cframe);
1023 
1024  if (ak == NULL) {
1025  /* Current frame is not a keyframe, so search. */
1026  const ActKeyColumn *pk = ED_keylist_find_prev(pso->keylist, cframe);
1027  const ActKeyColumn *nk = ED_keylist_find_next(pso->keylist, cframe);
1028 
1029  /* New set the frames. */
1030  /* Previous frame. */
1031  pso->prevFrame = (pk) ? (pk->cfra) : (pso->cframe - 1);
1032  RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
1033  /* Next frame. */
1034  pso->nextFrame = (nk) ? (nk->cfra) : (pso->cframe + 1);
1035  RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
1036  }
1037  else {
1038  /* Current frame itself is a keyframe, so just take keyframes on either side. */
1039  /* Previous frame. */
1040  pso->prevFrame = (ak->prev) ? (ak->prev->cfra) : (pso->cframe - 1);
1041  RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
1042  /* Next frame. */
1043  pso->nextFrame = (ak->next) ? (ak->next->cfra) : (pso->cframe + 1);
1044  RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
1045  }
1046 
1047  /* Apply NLA mapping corrections so the frame look-ups work. */
1048  for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
1049  tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
1050  if (ob_data->valid) {
1052  ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
1054  ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
1055  }
1056  }
1057 
1058  /* Initial apply for operator. */
1059  /* TODO: need to calculate factor for initial round too. */
1061  pose_slide_apply(C, pso);
1062  }
1063  else {
1065  }
1066 
1067  /* Depsgraph updates + redraws. */
1068  pose_slide_refresh(C, pso);
1069 
1070  /* Set cursor to indicate modal. */
1072 
1073  /* Header print. */
1074  pose_slide_draw_status(C, pso);
1075 
1076  /* Add a modal handler for this operator. */
1078 
1079  /* Save current bone visibility. */
1080  View3D *v3d = pso->area->spacedata.first;
1081  pso->overlay_flag = v3d->overlay.flag;
1082 
1083  return OPERATOR_RUNNING_MODAL;
1084 }
1085 
1090  tPoseSlideOp *pso,
1091  ePoseSlide_Channels channel)
1092 {
1093  /* Turn channel on or off? */
1094  if (pso->channels == channel) {
1095  /* Already limiting to transform only, so pressing this again turns it off */
1096  pso->channels = PS_TFM_ALL;
1097  }
1098  else {
1099  /* Only this set of channels */
1100  pso->channels = channel;
1101  }
1102  RNA_enum_set(op->ptr, "channels", pso->channels);
1103 
1104  /* Reset axis limits too for good measure */
1105  pso->axislock = 0;
1106  RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
1107 }
1108 
1113  tPoseSlideOp *pso,
1114  ePoseSlide_AxisLock axis)
1115 {
1116  /* Axis can only be set when a transform is set - it doesn't make sense otherwise */
1118  pso->axislock = 0;
1119  RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
1120  return false;
1121  }
1122 
1123  /* Turn on or off? */
1124  if (pso->axislock == axis) {
1125  /* Already limiting on this axis, so turn off */
1126  pso->axislock = 0;
1127  }
1128  else {
1129  /* Only this axis */
1130  pso->axislock = axis;
1131  }
1132  RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
1133 
1134  /* Setting changed, so pose update is needed */
1135  return true;
1136 }
1137 
1141 static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
1142 {
1143  tPoseSlideOp *pso = op->customdata;
1144  wmWindow *win = CTX_wm_window(C);
1145  bool do_pose_update = false;
1146 
1147  const bool has_numinput = hasNumInput(&pso->num);
1148 
1149  do_pose_update = ED_slider_modal(pso->slider, event);
1150 
1151  switch (event->type) {
1152  case LEFTMOUSE: /* Confirm. */
1153  case EVT_RETKEY:
1154  case EVT_PADENTER: {
1155  if (event->val == KM_PRESS) {
1156  /* Return to normal cursor and header status. */
1158  ED_area_status_text(pso->area, NULL);
1160 
1161  /* Depsgraph updates + redraws. Redraw needed to remove UI. */
1162  pose_slide_refresh(C, pso);
1163 
1164  /* Insert keyframes as required. */
1165  pose_slide_autoKeyframe(C, pso);
1166  pose_slide_exit(C, op);
1167 
1168  /* Done! */
1169  return OPERATOR_FINISHED;
1170  }
1171  break;
1172  }
1173 
1174  case EVT_ESCKEY: /* Cancel. */
1175  case RIGHTMOUSE: {
1176  if (event->val == KM_PRESS) {
1177  /* Return to normal cursor and header status. */
1179  ED_area_status_text(pso->area, NULL);
1181 
1182  /* Reset transforms back to original state. */
1183  pose_slide_reset(pso);
1184 
1185  /* Depsgraph updates + redraws. */
1186  pose_slide_refresh(C, pso);
1187 
1188  /* Clean up temp data. */
1189  pose_slide_exit(C, op);
1190 
1191  /* Canceled! */
1192  return OPERATOR_CANCELLED;
1193  }
1194  break;
1195  }
1196 
1197  /* Factor Change... */
1198  case MOUSEMOVE: /* Calculate new position. */
1199  {
1200  /* Only handle mouse-move if not doing numinput. */
1201  if (has_numinput == false) {
1202  /* Update pose to reflect the new values (see below). */
1203  do_pose_update = true;
1204  }
1205  break;
1206  }
1207  default: {
1208  if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) {
1209  float value;
1210 
1211  /* Grab percentage from numeric input, and store this new value for redo
1212  * NOTE: users see ints, while internally we use a 0-1 float
1213  */
1214  value = ED_slider_factor_get(pso->slider) * 100.0f;
1215  applyNumInput(&pso->num, &value);
1216 
1217  float factor = value / 100;
1218  CLAMP(factor, 0.0f, 1.0f);
1219  ED_slider_factor_set(pso->slider, factor);
1220  RNA_float_set(op->ptr, "factor", ED_slider_factor_get(pso->slider));
1221 
1222  /* Update pose to reflect the new values (see below) */
1223  do_pose_update = true;
1224  break;
1225  }
1226  if (event->val == KM_PRESS) {
1227  switch (event->type) {
1228  /* Transform Channel Limits. */
1229  /* XXX: Replace these hard-coded hotkeys with a modal-map that can be customized. */
1230  case EVT_GKEY: /* Location */
1231  {
1233  do_pose_update = true;
1234  break;
1235  }
1236  case EVT_RKEY: /* Rotation */
1237  {
1239  do_pose_update = true;
1240  break;
1241  }
1242  case EVT_SKEY: /* Scale */
1243  {
1245  do_pose_update = true;
1246  break;
1247  }
1248  case EVT_BKEY: /* Bendy Bones */
1249  {
1251  do_pose_update = true;
1252  break;
1253  }
1254  case EVT_CKEY: /* Custom Properties */
1255  {
1257  do_pose_update = true;
1258  break;
1259  }
1260 
1261  /* Axis Locks */
1262  /* XXX: Hardcoded... */
1263  case EVT_XKEY: {
1264  if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_X)) {
1265  do_pose_update = true;
1266  }
1267  break;
1268  }
1269  case EVT_YKEY: {
1270  if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Y)) {
1271  do_pose_update = true;
1272  }
1273  break;
1274  }
1275  case EVT_ZKEY: {
1276  if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Z)) {
1277  do_pose_update = true;
1278  }
1279  break;
1280  }
1281 
1282  /* Toggle Bone visibility. */
1283  case EVT_HKEY: {
1284  View3D *v3d = pso->area->spacedata.first;
1287  }
1288 
1289  default: /* Some other unhandled key... */
1290  break;
1291  }
1292  }
1293  else {
1294  /* Unhandled event - maybe it was some view manipulation? */
1295  /* Allow to pass through. */
1297  }
1298  }
1299  }
1300 
1301  /* Perform pose updates - in response to some user action
1302  * (e.g. pressing a key or moving the mouse). */
1303  if (do_pose_update) {
1304  RNA_float_set(op->ptr, "factor", ED_slider_factor_get(pso->slider));
1305 
1306  /* Update percentage indicator in header. */
1307  pose_slide_draw_status(C, pso);
1308 
1309  /* Reset transforms (to avoid accumulation errors). */
1310  pose_slide_reset(pso);
1311 
1312  /* Apply. */
1314  pose_slide_apply(C, pso);
1315  }
1316  else {
1318  }
1319  }
1320 
1321  /* Still running. */
1322  return OPERATOR_RUNNING_MODAL;
1323 }
1324 
1329 {
1330  /* Cleanup and done. */
1331  pose_slide_exit(C, op);
1332 }
1333 
1338 {
1339  /* Settings should have been set up ok for applying, so just apply! */
1341  pose_slide_apply(C, pso);
1342  }
1343  else {
1345  }
1346 
1347  /* Insert keyframes if needed. */
1348  pose_slide_autoKeyframe(C, pso);
1349 
1350  /* Cleanup and done. */
1351  pose_slide_exit(C, op);
1352 
1353  return OPERATOR_FINISHED;
1354 }
1355 
1360 {
1361  PropertyRNA *prop;
1362 
1363  prop = RNA_def_float_factor(ot->srna,
1364  "factor",
1365  0.5f,
1366  0.0f,
1367  1.0f,
1368  "Factor",
1369  "Weighting factor for which keyframe is favored more",
1370  0.0,
1371  1.0);
1373 
1374  prop = RNA_def_int(ot->srna,
1375  "prev_frame",
1376  0,
1377  MINAFRAME,
1378  MAXFRAME,
1379  "Previous Keyframe",
1380  "Frame number of keyframe immediately before the current frame",
1381  0,
1382  50);
1384 
1385  prop = RNA_def_int(ot->srna,
1386  "next_frame",
1387  0,
1388  MINAFRAME,
1389  MAXFRAME,
1390  "Next Keyframe",
1391  "Frame number of keyframe immediately after the current frame",
1392  0,
1393  50);
1395 
1396  prop = RNA_def_enum(ot->srna,
1397  "channels",
1399  PS_TFM_ALL,
1400  "Channels",
1401  "Set of properties that are affected");
1403  prop = RNA_def_enum(ot->srna,
1404  "axis_lock",
1406  0,
1407  "Axis Lock",
1408  "Transform axis to restrict effects to");
1410 }
1411 
1412 /* ------------------------------------ */
1413 
1417 static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1418 {
1419  /* Initialize data. */
1420  if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
1421  pose_slide_exit(C, op);
1422  return OPERATOR_CANCELLED;
1423  }
1424 
1425  /* Do common setup work. */
1426  return pose_slide_invoke_common(C, op, event);
1427 }
1428 
1433 {
1434  tPoseSlideOp *pso;
1435 
1436  /* Initialize data (from RNA-props). */
1437  if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
1438  pose_slide_exit(C, op);
1439  return OPERATOR_CANCELLED;
1440  }
1441 
1442  pso = op->customdata;
1443 
1444  /* Do common exec work. */
1445  return pose_slide_exec_common(C, op, pso);
1446 }
1447 
1449 {
1450  /* identifiers */
1451  ot->name = "Push Pose from Breakdown";
1452  ot->idname = "POSE_OT_push";
1453  ot->description = "Exaggerate the current pose in regards to the breakdown pose";
1454 
1455  /* callbacks */
1461 
1462  /* flags */
1464 
1465  /* Properties */
1467 }
1468 
1469 /* ........................ */
1470 
1474 static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1475 {
1476  /* Initialize data. */
1477  if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
1478  pose_slide_exit(C, op);
1479  return OPERATOR_CANCELLED;
1480  }
1481 
1482  /* Do common setup work. */
1483  return pose_slide_invoke_common(C, op, event);
1484 }
1485 
1490 {
1491  tPoseSlideOp *pso;
1492 
1493  /* Initialize data (from RNA-props). */
1494  if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
1495  pose_slide_exit(C, op);
1496  return OPERATOR_CANCELLED;
1497  }
1498 
1499  pso = op->customdata;
1500 
1501  /* Do common exec work. */
1502  return pose_slide_exec_common(C, op, pso);
1503 }
1504 
1506 {
1507  /* identifiers */
1508  ot->name = "Relax Pose to Breakdown";
1509  ot->idname = "POSE_OT_relax";
1510  ot->description = "Make the current pose more similar to its breakdown pose";
1511 
1512  /* callbacks */
1518 
1519  /* flags */
1521 
1522  /* Properties */
1524 }
1525 
1526 /* ........................ */
1531 {
1532  /* Initialize data. */
1533  if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) {
1534  pose_slide_exit(C, op);
1535  return OPERATOR_CANCELLED;
1536  }
1537 
1538  /* do common setup work */
1539  return pose_slide_invoke_common(C, op, event);
1540 }
1541 
1546 {
1547  tPoseSlideOp *pso;
1548 
1549  /* Initialize data (from RNA-props). */
1550  if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) {
1551  pose_slide_exit(C, op);
1552  return OPERATOR_CANCELLED;
1553  }
1554 
1555  pso = op->customdata;
1556 
1557  /* Do common exec work. */
1558  return pose_slide_exec_common(C, op, pso);
1559 }
1560 
1562 {
1563  /* identifiers */
1564  ot->name = "Push Pose from Rest Pose";
1565  ot->idname = "POSE_OT_push_rest";
1566  ot->description = "Push the current pose further away from the rest pose";
1567 
1568  /* callbacks */
1574 
1575  /* flags */
1577 
1578  /* Properties */
1580 }
1581 
1582 /* ........................ */
1583 
1588 {
1589  /* Initialize data. */
1590  if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) {
1591  pose_slide_exit(C, op);
1592  return OPERATOR_CANCELLED;
1593  }
1594 
1595  /* Do common setup work. */
1596  return pose_slide_invoke_common(C, op, event);
1597 }
1598 
1603 {
1604  tPoseSlideOp *pso;
1605 
1606  /* Initialize data (from RNA-props). */
1607  if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) {
1608  pose_slide_exit(C, op);
1609  return OPERATOR_CANCELLED;
1610  }
1611 
1612  pso = op->customdata;
1613 
1614  /* Do common exec work. */
1615  return pose_slide_exec_common(C, op, pso);
1616 }
1617 
1619 {
1620  /* identifiers */
1621  ot->name = "Relax Pose to Rest Pose";
1622  ot->idname = "POSE_OT_relax_rest";
1623  ot->description = "Make the current pose more similar to the rest pose";
1624 
1625  /* callbacks */
1631 
1632  /* flags */
1634 
1635  /* Properties */
1637 }
1638 
1639 /* ........................ */
1640 
1645 {
1646  /* Initialize data. */
1647  if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
1648  pose_slide_exit(C, op);
1649  return OPERATOR_CANCELLED;
1650  }
1651 
1652  /* Do common setup work. */
1653  return pose_slide_invoke_common(C, op, event);
1654 }
1655 
1660 {
1661  tPoseSlideOp *pso;
1662 
1663  /* Initialize data (from RNA-props). */
1664  if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
1665  pose_slide_exit(C, op);
1666  return OPERATOR_CANCELLED;
1667  }
1668 
1669  pso = op->customdata;
1670 
1671  /* Do common exec work. */
1672  return pose_slide_exec_common(C, op, pso);
1673 }
1674 
1676 {
1677  /* identifiers */
1678  ot->name = "Pose Breakdowner";
1679  ot->idname = "POSE_OT_breakdown";
1680  ot->description = "Create a suitable breakdown pose on the current frame";
1681 
1682  /* callbacks */
1688 
1689  /* flags */
1691 
1692  /* Properties */
1694 }
1695 
1696 /* ........................ */
1698 {
1699  /* Initialize data. */
1700  if (pose_slide_init(C, op, POSESLIDE_BLEND) == 0) {
1701  pose_slide_exit(C, op);
1702  return OPERATOR_CANCELLED;
1703  }
1704 
1705  /* Do common setup work. */
1706  return pose_slide_invoke_common(C, op, event);
1707 }
1708 
1710 {
1711  tPoseSlideOp *pso;
1712 
1713  /* Initialize data (from RNA-props). */
1714  if (pose_slide_init(C, op, POSESLIDE_BLEND) == 0) {
1715  pose_slide_exit(C, op);
1716  return OPERATOR_CANCELLED;
1717  }
1718 
1719  pso = op->customdata;
1720 
1721  /* Do common exec work. */
1722  return pose_slide_exec_common(C, op, pso);
1723 }
1724 
1726 {
1727  /* Identifiers. */
1728  ot->name = "Blend to Neighbor";
1729  ot->idname = "POSE_OT_blend_to_neighbor";
1730  ot->description = "Blend from current position to previous or next keyframe";
1731 
1732  /* Callbacks. */
1738 
1739  /* Flags. */
1741 
1742  /* Properties. */
1744 }
1745 
1746 /* **************************************************** */
1747 /* B) Pose Propagate */
1748 
1749 /* "termination conditions" - i.e. when we stop */
1761 
1767 
1774  float end_frame;
1775 
1779 
1780 /* --------------------------------- */
1781 
1788 static float pose_propagate_get_boneHoldEndFrame(tPChanFCurveLink *pfl, float startFrame)
1789 {
1790  struct AnimKeylist *keylist = ED_keylist_create();
1791 
1792  Object *ob = pfl->ob;
1793  AnimData *adt = ob->adt;
1794  LinkData *ld;
1795  float endFrame = startFrame;
1796 
1797  for (ld = pfl->fcurves.first; ld; ld = ld->next) {
1798  FCurve *fcu = (FCurve *)ld->data;
1799  fcurve_to_keylist(adt, fcu, keylist, 0);
1800  }
1802 
1803  /* Find the long keyframe (i.e. hold), and hence obtain the endFrame value
1804  * - the best case would be one that starts on the frame itself
1805  */
1806  const ActKeyColumn *ab = ED_keylist_find_exact(keylist, startFrame);
1807 
1808  /* There are only two cases for no-exact match:
1809  * 1) the current frame is just before another key but not on a key itself
1810  * 2) the current frame is on a key, but that key doesn't link to the next
1811  *
1812  * If we've got the first case, then we can search for another block,
1813  * otherwise forget it, as we'd be overwriting some valid data.
1814  */
1815  if (ab == NULL) {
1816  /* We've got case 1, so try the one after. */
1817  ab = ED_keylist_find_next(keylist, startFrame);
1818 
1820  /* Try the block before this frame then as last resort. */
1821  ab = ED_keylist_find_prev(keylist, startFrame);
1822  }
1823  }
1824 
1825  /* Whatever happens, stop searching now.... */
1827  /* Restrict range to just the frame itself
1828  * i.e. everything is in motion, so no holds to safely overwrite. */
1829  ab = NULL;
1830  }
1831 
1832  /* Check if we can go any further than we've already gone. */
1833  if (ab) {
1834  /* Go to next if it is also valid and meets "extension" criteria. */
1835  while (ab->next) {
1836  const ActKeyColumn *abn = ab->next;
1837 
1838  /* Must be valid. */
1840  break;
1841  }
1842  /* Should have the same number of curves. */
1843  if (ab->totblock != abn->totblock) {
1844  break;
1845  }
1846 
1847  /* We can extend the bounds to the end of this "next" block now. */
1848  ab = abn;
1849  }
1850 
1851  /* End frame can now take the value of the end of the block. */
1852  endFrame = ab->next->cfra;
1853  }
1854 
1855  /* Free temp memory. */
1856  ED_keylist_free(keylist);
1857 
1858  /* Return the end frame we've found. */
1859  return endFrame;
1860 }
1861 
1865 static bool pose_propagate_get_refVal(Object *ob, FCurve *fcu, float *value)
1866 {
1867  PointerRNA id_ptr, ptr;
1868  PropertyRNA *prop;
1869  bool found = false;
1870 
1871  /* Base pointer is always the `object -> id_ptr`. */
1872  RNA_id_pointer_create(&ob->id, &id_ptr);
1873 
1874  /* Resolve the property. */
1875  if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
1876  if (RNA_property_array_check(prop)) {
1877  /* Array. */
1878  if (fcu->array_index < RNA_property_array_length(&ptr, prop)) {
1879  found = true;
1880  switch (RNA_property_type(prop)) {
1881  case PROP_BOOLEAN:
1882  *value = (float)RNA_property_boolean_get_index(&ptr, prop, fcu->array_index);
1883  break;
1884  case PROP_INT:
1885  *value = (float)RNA_property_int_get_index(&ptr, prop, fcu->array_index);
1886  break;
1887  case PROP_FLOAT:
1888  *value = RNA_property_float_get_index(&ptr, prop, fcu->array_index);
1889  break;
1890  default:
1891  found = false;
1892  break;
1893  }
1894  }
1895  }
1896  else {
1897  /* Not an array. */
1898  found = true;
1899  switch (RNA_property_type(prop)) {
1900  case PROP_BOOLEAN:
1901  *value = (float)RNA_property_boolean_get(&ptr, prop);
1902  break;
1903  case PROP_INT:
1904  *value = (float)RNA_property_int_get(&ptr, prop);
1905  break;
1906  case PROP_ENUM:
1907  *value = (float)RNA_property_enum_get(&ptr, prop);
1908  break;
1909  case PROP_FLOAT:
1910  *value = RNA_property_float_get(&ptr, prop);
1911  break;
1912  default:
1913  found = false;
1914  break;
1915  }
1916  }
1917  }
1918 
1919  return found;
1920 }
1921 
1926  wmOperator *op, Object *ob, FCurve *fcu, float startFrame, tPosePropagate_ModeData modeData)
1927 {
1928  const int mode = RNA_enum_get(op->ptr, "mode");
1929 
1930  BezTriple *bezt;
1931  float refVal = 0.0f;
1932  bool keyExists;
1933  int i;
1934  bool first = true;
1935 
1936  /* Skip if no keyframes to edit. */
1937  if ((fcu->bezt == NULL) || (fcu->totvert < 2)) {
1938  return;
1939  }
1940 
1941  /* Find the reference value from bones directly, which means that the user
1942  * doesn't need to firstly keyframe the pose (though this doesn't mean that
1943  * they can't either). */
1944  if (!pose_propagate_get_refVal(ob, fcu, &refVal)) {
1945  return;
1946  }
1947 
1948  /* Find the first keyframe to start propagating from:
1949  * - if there's a keyframe on the current frame, we probably want to save this value there too
1950  * since it may be as of yet un-keyed
1951  * - if starting before the starting frame, don't touch the key, as it may have had some valid
1952  * values
1953  * - if only doing selected keyframes, start from the first one
1954  */
1955  if (mode != POSE_PROPAGATE_SELECTED_KEYS) {
1956  const int match = BKE_fcurve_bezt_binarysearch_index(
1957  fcu->bezt, startFrame, fcu->totvert, &keyExists);
1958 
1959  if (fcu->bezt[match].vec[1][0] < startFrame) {
1960  i = match + 1;
1961  }
1962  else {
1963  i = match;
1964  }
1965  }
1966  else {
1967  /* Selected - start from first keyframe. */
1968  i = 0;
1969  }
1970 
1971  for (bezt = &fcu->bezt[i]; i < fcu->totvert; i++, bezt++) {
1972  /* Additional termination conditions based on the operator 'mode' property go here. */
1974  /* Stop if keyframe is outside the accepted range. */
1975  if (bezt->vec[1][0] > modeData.end_frame) {
1976  break;
1977  }
1978  }
1979  else if (mode == POSE_PROPAGATE_NEXT_KEY) {
1980  /* Stop after the first keyframe has been processed. */
1981  if (first == false) {
1982  break;
1983  }
1984  }
1985  else if (mode == POSE_PROPAGATE_LAST_KEY) {
1986  /* Only affect this frame if it will be the last one. */
1987  if (i != (fcu->totvert - 1)) {
1988  continue;
1989  }
1990  }
1991  else if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
1992  /* Only allow if there's a marker on this frame. */
1993  CfraElem *ce = NULL;
1994 
1995  /* Stop on matching marker if there is one. */
1996  for (ce = modeData.sel_markers.first; ce; ce = ce->next) {
1997  if (ce->cfra == round_fl_to_int(bezt->vec[1][0])) {
1998  break;
1999  }
2000  }
2001 
2002  /* Skip this keyframe if no marker. */
2003  if (ce == NULL) {
2004  continue;
2005  }
2006  }
2007  else if (mode == POSE_PROPAGATE_SELECTED_KEYS) {
2008  /* Only allow if this keyframe is already selected - skip otherwise. */
2009  if (BEZT_ISSEL_ANY(bezt) == 0) {
2010  continue;
2011  }
2012  }
2013 
2014  /* Just flatten handles, since values will now be the same either side. */
2015  /* TODO: perhaps a fade-out modulation of the value is required here (optional once again)? */
2016  bezt->vec[0][1] = bezt->vec[1][1] = bezt->vec[2][1] = refVal;
2017 
2018  /* Select keyframe to indicate that it's been changed. */
2019  bezt->f2 |= SELECT;
2020  first = false;
2021  }
2022 }
2023 
2024 /* --------------------------------- */
2025 
2027 {
2029  ViewLayer *view_layer = CTX_data_view_layer(C);
2030  View3D *v3d = CTX_wm_view3d(C);
2031 
2032  ListBase pflinks = {NULL, NULL};
2033  tPChanFCurveLink *pfl;
2034 
2035  tPosePropagate_ModeData modeData;
2036  const int mode = RNA_enum_get(op->ptr, "mode");
2037 
2038  /* Isolate F-Curves related to the selected bones. */
2039  poseAnim_mapping_get(C, &pflinks);
2040 
2041  if (BLI_listbase_is_empty(&pflinks)) {
2042  /* There is a change the reason the list is empty is
2043  * that there is no valid object to propagate poses for.
2044  * This is very unlikely though, so we focus on the most likely issue. */
2045  BKE_report(op->reports, RPT_ERROR, "No keyframed poses to propagate to");
2046  return OPERATOR_CANCELLED;
2047  }
2048 
2049  /* Mode-specific data preprocessing (requiring no access to curves). */
2050  if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
2051  /* Get a list of selected markers. */
2053  }
2054  else {
2055  /* Assume everything else wants endFrame. */
2056  modeData.end_frame = RNA_float_get(op->ptr, "end_frame");
2057  }
2058 
2059  /* For each bone, perform the copying required. */
2060  for (pfl = pflinks.first; pfl; pfl = pfl->next) {
2061  LinkData *ld;
2062 
2063  /* Mode-specific data preprocessing (requiring access to all curves). */
2064  if (mode == POSE_PROPAGATE_SMART_HOLDS) {
2065  /* We store in endFrame the end frame of the "long keyframe" (i.e. a held value) starting
2066  * from the keyframe that occurs after the current frame. */
2067  modeData.end_frame = pose_propagate_get_boneHoldEndFrame(pfl, (float)scene->r.cfra);
2068  }
2069 
2070  /* Go through propagating pose to keyframes, curve by curve. */
2071  for (ld = pfl->fcurves.first; ld; ld = ld->next) {
2072  pose_propagate_fcurve(op, pfl->ob, (FCurve *)ld->data, (float)scene->r.cfra, modeData);
2073  }
2074  }
2075 
2076  /* Free temp data. */
2077  poseAnim_mapping_free(&pflinks);
2078 
2079  if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
2080  BLI_freelistN(&modeData.sel_markers);
2081  }
2082 
2083  /* Updates + notifiers. */
2084  FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
2086  }
2088 
2089  return OPERATOR_FINISHED;
2090 }
2091 
2092 /* --------------------------------- */
2093 
2095 {
2096  static const EnumPropertyItem terminate_items[] = {
2098  "WHILE_HELD",
2099  0,
2100  "While Held",
2101  "Propagate pose to all keyframes after current frame that don't change (Default behavior)"},
2103  "NEXT_KEY",
2104  0,
2105  "To Next Keyframe",
2106  "Propagate pose to first keyframe following the current frame only"},
2108  "LAST_KEY",
2109  0,
2110  "To Last Keyframe",
2111  "Propagate pose to the last keyframe only (i.e. making action cyclic)"},
2113  "BEFORE_FRAME",
2114  0,
2115  "Before Frame",
2116  "Propagate pose to all keyframes between current frame and 'Frame' property"},
2118  "BEFORE_END",
2119  0,
2120  "Before Last Keyframe",
2121  "Propagate pose to all keyframes from current frame until no more are found"},
2123  "SELECTED_KEYS",
2124  0,
2125  "On Selected Keyframes",
2126  "Propagate pose to all selected keyframes"},
2128  "SELECTED_MARKERS",
2129  0,
2130  "On Selected Markers",
2131  "Propagate pose to all keyframes occurring on frames with Scene Markers after the current "
2132  "frame"},
2133  {0, NULL, 0, NULL, NULL},
2134  };
2135 
2136  /* identifiers */
2137  ot->name = "Propagate Pose";
2138  ot->idname = "POSE_OT_propagate";
2139  ot->description =
2140  "Copy selected aspects of the current pose to subsequent poses already keyframed";
2141 
2142  /* callbacks */
2144  ot->poll = ED_operator_posemode; /* XXX: needs selected bones! */
2145 
2146  /* flag */
2148 
2149  /* properties */
2150  /* TODO: add "fade out" control for tapering off amount of propagation as time goes by? */
2151  ot->prop = RNA_def_enum(ot->srna,
2152  "mode",
2153  terminate_items,
2155  "Terminate Mode",
2156  "Method used to determine when to stop propagating pose to keyframes");
2158  "end_frame",
2159  250.0,
2160  FLT_MIN,
2161  FLT_MAX,
2162  "End Frame",
2163  "Frame to stop propagating frames to (for 'Before Frame' mode)",
2164  1.0,
2165  250.0);
2166 }
2167 
2168 /* **************************************************** */
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
float evaluate_fcurve(struct FCurve *fcu, float evaltime)
Definition: fcurve.c:2135
int BKE_fcurve_bezt_binarysearch_index(const struct BezTriple array[], float frame, int arraylen, bool *r_replace)
Definition: fcurve.c:561
#define BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, v3d, r_len, mode)
Definition: BKE_layer.h:560
#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
@ NLATIME_CONVERT_UNMAP
Definition: BKE_nla.h:357
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode)
Definition: nla.c:642
General operations, lookup, etc. for blender objects.
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
@ B_UNIT_NONE
Definition: BKE_unit.h:100
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
MINLINE int round_fl_to_int(float a)
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], float t)
float normalize_qt(float q[4])
float normalize_qt_qt(float r[4], const float q[4])
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
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
#define STRNCPY(dst, src)
Definition: BLI_string.h:483
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned int uint
Definition: BLI_sys_types.h:67
#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 MAXFRAME
@ V3D_OVERLAY_HIDE_BONES
@ 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:87
void initNumInput(NumInput *n)
Definition: numinput.c:69
#define NUM_STR_REP_LEN
Definition: ED_numinput.h:13
@ NUM_NO_NEGATIVE
Definition: ED_numinput.h:56
bool applyNumInput(NumInput *n, float *vec)
Definition: numinput.c:189
bool hasNumInput(const NumInput *n)
Definition: numinput.c:170
bool handleNumInput(struct bContext *C, NumInput *n, const struct wmEvent *event)
bool ED_operator_posemode(struct bContext *C)
Definition: screen_ops.c:530
void ED_area_status_text(ScrArea *area, const char *str)
Definition: area.c:792
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:655
void ED_workspace_status_text(struct bContext *C, const char *str)
Definition: area.c:816
void ED_slider_init(struct tSlider *slider, const struct wmEvent *event)
void ED_slider_status_string_get(const struct tSlider *slider, char *status_string, size_t size_of_status_string)
Definition: ed_draw.c:424
float ED_slider_factor_get(struct tSlider *slider)
Definition: ed_draw.c:480
bool ED_slider_modal(struct tSlider *slider, const struct wmEvent *event)
void ED_slider_factor_set(struct tSlider *slider, float factor)
Definition: ed_draw.c:485
void ED_slider_destroy(struct bContext *C, struct tSlider *slider)
Definition: ed_draw.c:467
struct tSlider * ED_slider_create(struct bContext *C)
Definition: ed_draw.c:358
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
@ PROP_FLOAT
Definition: RNA_types.h:61
@ PROP_BOOLEAN
Definition: RNA_types.h:59
@ PROP_ENUM
Definition: RNA_types.h:63
@ PROP_INT
Definition: RNA_types.h:60
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
#define C
Definition: RandGen.cpp:25
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:91
@ KM_PRESS
Definition: WM_types.h:267
@ OPTYPE_BLOCKING
Definition: WM_types.h:150
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
@ OPTYPE_GRAB_CURSOR_X
Definition: WM_types.h:156
void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel)
Definition: anim_markers.c:296
void poseAnim_mapping_free(ListBase *pfLinks)
Definition: pose_utils.c:175
void poseAnim_mapping_reset(ListBase *pfLinks)
Definition: pose_utils.c:212
LinkData * poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, const char *path)
Definition: pose_utils.c:316
void poseAnim_mapping_autoKeyframe(struct bContext *C, struct Scene *scene, ListBase *pfLinks, float cframe)
Definition: pose_utils.c:248
void poseAnim_mapping_get(struct bContext *C, ListBase *pfLinks)
Definition: pose_utils.c:130
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:121
volatile int lock
#define SELECT
Scene scene
int len
Definition: draw_manager.c:108
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, const int saction_flag)
AnimKeylist * ED_keylist_create()
bool ED_keylist_is_empty(const struct AnimKeylist *keylist)
void ED_keylist_prepare_for_direct_access(AnimKeylist *keylist)
const ActKeyColumn * ED_keylist_find_next(const AnimKeylist *keylist, const float cfra)
int actkeyblock_get_valid_hold(const ActKeyColumn *ac)
void ED_keylist_free(AnimKeylist *keylist)
const ActKeyColumn * ED_keylist_find_prev(const AnimKeylist *keylist, const float cfra)
const ActKeyColumn * ED_keylist_find_exact(const AnimKeylist *keylist, const float cfra)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
ccl_device_inline float2 fabs(const float2 &a)
Definition: math_float2.h:222
ePoseSlide_Modes
Definition: pose_slide.c:97
@ POSESLIDE_BLEND
Definition: pose_slide.c:106
@ POSESLIDE_BREAKDOWN
Definition: pose_slide.c:103
@ POSESLIDE_PUSH
Definition: pose_slide.c:99
@ POSESLIDE_PUSH_REST
Definition: pose_slide.c:104
@ POSESLIDE_RELAX_REST
Definition: pose_slide.c:105
@ POSESLIDE_RELAX
Definition: pose_slide.c:101
static void pose_slide_toggle_channels_mode(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_Channels channel)
Definition: pose_slide.c:1089
void POSE_OT_relax_rest(wmOperatorType *ot)
Definition: pose_slide.c:1618
static int pose_slide_invoke_common(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:991
static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
Definition: pose_slide.c:782
void POSE_OT_breakdown(wmOperatorType *ot)
Definition: pose_slide.c:1675
static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1417
static int pose_slide_relax_rest_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:1602
static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1474
static int pose_slide_relax_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1587
static const EnumPropertyItem prop_channels_types[]
Definition: pose_slide.c:178
union tPosePropagate_ModeData tPosePropagate_ModeData
static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1141
static void pose_slide_reset(tPoseSlideOp *pso)
Definition: pose_slide.c:869
static bool pose_propagate_get_refVal(Object *ob, FCurve *fcu, float *value)
Definition: pose_slide.c:1865
struct tPoseSlideOp tPoseSlideOp
static void pose_slide_cancel(bContext *C, wmOperator *op)
Definition: pose_slide.c:1328
static int pose_slide_blend_to_neighbors_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1697
static int pose_slide_push_rest_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:1545
ePoseSlide_AxisLock
Definition: pose_slide.c:90
@ PS_LOCK_Z
Definition: pose_slide.c:93
@ PS_LOCK_Y
Definition: pose_slide.c:92
@ PS_LOCK_X
Definition: pose_slide.c:91
static const EnumPropertyItem prop_axis_lock_types[]
Definition: pose_slide.c:193
static bool pose_slide_toggle_axis_locks(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_AxisLock axis)
Definition: pose_slide.c:1112
static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, float *val)
Definition: pose_slide.c:353
static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso)
Definition: pose_slide.c:1337
void POSE_OT_push_rest(wmOperatorType *ot)
Definition: pose_slide.c:1561
static void pose_slide_rest_pose_apply_other_rot(tPoseSlideOp *pso, float vec[4], bool quat)
Definition: pose_slide.c:699
struct tPoseSlideObject tPoseSlideObject
static void pose_slide_opdef_properties(wmOperatorType *ot)
Definition: pose_slide.c:1359
static void pose_slide_refresh(bContext *C, tPoseSlideOp *pso)
Definition: pose_slide.c:316
static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
Definition: pose_slide.c:558
static float pose_propagate_get_boneHoldEndFrame(tPChanFCurveLink *pfl, float startFrame)
Definition: pose_slide.c:1788
static int pose_slide_blend_to_neighbors_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:1709
void POSE_OT_propagate(wmOperatorType *ot)
Definition: pose_slide.c:2094
static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso)
Definition: pose_slide.c:723
static bool pose_frame_range_from_object_get(tPoseSlideOp *pso, Object *ob, float *prevFrameF, float *nextFrameF)
Definition: pose_slide.c:331
static void pose_slide_autoKeyframe(bContext *C, tPoseSlideOp *pso)
Definition: pose_slide.c:860
static int pose_slide_breakdown_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:1659
static int pose_slide_push_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1530
static int pose_slide_push_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:1432
static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu, float startFrame, tPosePropagate_ModeData modeData)
Definition: pose_slide.c:1925
static int pose_propagate_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:2026
void POSE_OT_relax(wmOperatorType *ot)
Definition: pose_slide.c:1505
static void pose_slide_apply_vec3(tPoseSlideOp *pso, tPChanFCurveLink *pfl, float vec[3], const char propName[])
Definition: pose_slide.c:445
ePoseSlide_Channels
Definition: pose_slide.c:110
@ PS_TFM_SIZE
Definition: pose_slide.c:115
@ PS_TFM_LOC
Definition: pose_slide.c:113
@ PS_TFM_PROPS
Definition: pose_slide.c:119
@ PS_TFM_ALL
Definition: pose_slide.c:111
@ PS_TFM_BBONE_SHAPE
Definition: pose_slide.c:117
@ PS_TFM_ROT
Definition: pose_slide.c:114
static int pose_slide_relax_exec(bContext *C, wmOperator *op)
Definition: pose_slide.c:1489
void POSE_OT_push(wmOperatorType *ot)
Definition: pose_slide.c:1448
static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode)
Definition: pose_slide.c:205
static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_slide.c:1644
static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], float default_value)
Definition: pose_slide.c:680
static void pose_slide_draw_status(bContext *C, tPoseSlideOp *pso)
Definition: pose_slide.c:882
ePosePropagate_Termination
Definition: pose_slide.c:1750
@ POSE_PROPAGATE_LAST_KEY
Definition: pose_slide.c:1754
@ POSE_PROPAGATE_BEFORE_FRAME
Definition: pose_slide.c:1758
@ POSE_PROPAGATE_SELECTED_MARKERS
Definition: pose_slide.c:1765
@ POSE_PROPAGATE_BEFORE_END
Definition: pose_slide.c:1760
@ POSE_PROPAGATE_SMART_HOLDS
Definition: pose_slide.c:1752
@ POSE_PROPAGATE_NEXT_KEY
Definition: pose_slide.c:1756
@ POSE_PROPAGATE_SELECTED_KEYS
Definition: pose_slide.c:1763
static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl, const char prop_prefix[])
Definition: pose_slide.c:479
static void pose_slide_exit(bContext *C, wmOperator *op)
Definition: pose_slide.c:282
void POSE_OT_blend_to_neighbors(wmOperatorType *ot)
Definition: pose_slide.c:1725
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2767
void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
Definition: rna_access.c:2449
bool RNA_property_array_check(PropertyRNA *prop)
Definition: rna_access.c:1080
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:112
int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:2581
float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:2954
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1010
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:4921
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2153
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2429
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
Definition: rna_access.c:2180
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:4968
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1075
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3402
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
Definition: rna_access.c:2790
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:2275
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
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:3836
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:4144
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
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:3597
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:3783
bool RNA_path_resolve_property(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition: rna_path.cc:531
struct ActKeyColumn * next
float vec[3][3]
uint8_t f2
float cfra
Definition: BKE_fcurve.h:40
struct CfraElem * next
Definition: BKE_fcurve.h:39
char * rna_path
BezTriple * bezt
int array_index
unsigned int totvert
void * data
Definition: DNA_listBase.h:26
struct LinkData * next
Definition: DNA_listBase.h:25
void * first
Definition: DNA_listBase.h:31
short idx_max
Definition: ED_numinput.h:20
short val_flag[NUM_MAX_ELEMENTS]
Definition: ED_numinput.h:29
int unit_type[NUM_MAX_ELEMENTS]
Definition: ED_numinput.h:23
struct bPose * pose
struct AnimData * adt
struct RenderData r
struct UnitSettings unit
ListBase markers
ListBase spacedata
View3DOverlay overlay
short flag
ePoseSlide_Channels channels
Definition: pose_slide.c:155
NumInput num
Definition: pose_slide.c:162
ePoseSlide_AxisLock axislock
Definition: pose_slide.c:157
int overlay_flag
Definition: pose_slide.c:152
ARegion * region
Definition: pose_slide.c:129
struct tSlider * slider
Definition: pose_slide.c:159
ScrArea * area
Definition: pose_slide.c:127
struct AnimKeylist * keylist
Definition: pose_slide.c:136
struct tPoseSlideObject * ob_data_array
Definition: pose_slide.c:164
ePoseSlide_Modes mode
Definition: pose_slide.c:147
ListBase pfLinks
Definition: pose_slide.c:134
Scene * scene
Definition: pose_slide.c:125
uint objects_len
Definition: pose_slide.c:131
short val
Definition: WM_types.h:680
short type
Definition: WM_types.h:678
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct PointerRNA * ptr
void WM_cursor_modal_set(wmWindow *win, int val)
Definition: wm_cursors.c:191
void WM_cursor_modal_restore(wmWindow *win)
Definition: wm_cursors.c:200
@ WM_CURSOR_EW_SCROLL
Definition: wm_cursors.h:53
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
@ EVT_HKEY
@ LEFTMOUSE
@ EVT_ZKEY
@ EVT_ESCKEY
@ EVT_RKEY
@ EVT_BKEY
@ EVT_RETKEY
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479