Blender V4.5
pose_slide.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors, Joshua Leung.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
30
31#include "MEM_guardedalloc.h"
32
33#include "BLI_array.hh"
34#include "BLI_listbase.h"
35#include "BLI_math_rotation.h"
36#include "BLI_string.h"
37
38#include "BLT_translation.hh"
39
40#include "DNA_anim_types.h"
41#include "DNA_object_types.h"
42#include "DNA_scene_types.h"
43
44#include "BKE_fcurve.hh"
45#include "BKE_nla.hh"
46
47#include "BKE_context.hh"
48#include "BKE_layer.hh"
49#include "BKE_report.hh"
50#include "BKE_scene.hh"
51#include "BKE_unit.hh"
52
53#include "RNA_access.hh"
54#include "RNA_define.hh"
55#include "RNA_prototypes.hh"
56
57#include "WM_api.hh"
58#include "WM_types.hh"
59
60#include "UI_interface.hh"
61
62#include "ED_keyframes_edit.hh"
64#include "ED_markers.hh"
65#include "ED_numinput.hh"
66#include "ED_screen.hh"
67#include "ED_util.hh"
68
69#include "ANIM_fcurve.hh"
70
71#include "armature_intern.hh"
72
73using blender::Vector;
74
75/* **************************************************** */
76/* A) Push & Relax, Breakdowner */
77
80 PS_LOCK_X = (1 << 0),
81 PS_LOCK_Y = (1 << 1),
82 PS_LOCK_Z = (1 << 2),
83};
84
96
99 PS_TFM_ALL = 0, /* All transforms and properties */
100
101 PS_TFM_LOC, /* Loc/Rot/Scale */
104
105 PS_TFM_BBONE_SHAPE, /* Bendy Bones */
106
107 PS_TFM_PROPS, /* Custom Properties */
108};
109
119
129
134
137
142
146 // short flag;
147
148 /* Store overlay settings when invoking the operator. Bones will be temporarily hidden. */
150
155
157
160
162};
163
166 {PS_TFM_ALL,
167 "ALL",
168 0,
169 "All Properties",
170 "All properties, including transforms, bendy bone shape, and custom properties"},
171 {PS_TFM_LOC, "LOC", 0, "Location", "Location only"},
172 {PS_TFM_ROT, "ROT", 0, "Rotation", "Rotation only"},
173 /* NOTE: `SIZE` identifier is only used for compatibility, should be `SCALE`. */
174 {PS_TFM_SCALE, "SIZE", 0, "Scale", "Scale only"},
175 {PS_TFM_BBONE_SHAPE, "BBONE", 0, "Bendy Bone", "Bendy Bone shape properties"},
176 {PS_TFM_PROPS, "CUSTOM", 0, "Custom Properties", "Custom properties"},
177 {0, nullptr, 0, nullptr, nullptr},
178};
179
180/* Property enum for ePoseSlide_AxisLock */
182 {0, "FREE", 0, "Free", "All axes are affected"},
183 {PS_LOCK_X, "X", 0, "X", "Only X-axis transforms are affected"},
184 {PS_LOCK_Y, "Y", 0, "Y", "Only Y-axis transforms are affected"},
185 {PS_LOCK_Z, "Z", 0, "Z", "Only Z-axis transforms are affected"}, /* TODO: Combinations? */
186 {0, nullptr, 0, nullptr, nullptr},
187};
188
189/* ------------------------------------ */
190
193{
194 tPoseSlideOp *pso = MEM_new<tPoseSlideOp>(__func__);
195 op->customdata = pso;
196
197 /* Get info from context. */
198 pso->scene = CTX_data_scene(C);
199 pso->area = CTX_wm_area(C); /* Only really needed when doing modal(). */
200 pso->region = CTX_wm_region(C); /* Only really needed when doing modal(). */
201
202 pso->current_frame = pso->scene->r.cfra;
203 pso->mode = mode;
204
205 /* Set range info from property values - these may get overridden for the invoke(). */
206 pso->prev_frame = RNA_int_get(op->ptr, "prev_frame");
207 pso->next_frame = RNA_int_get(op->ptr, "next_frame");
208
209 /* Get the set of properties/axes that can be operated on. */
210 pso->channels = ePoseSlide_Channels(RNA_enum_get(op->ptr, "channels"));
211 pso->axislock = ePoseSlide_AxisLock(RNA_enum_get(op->ptr, "axis_lock"));
212
213 pso->slider = ED_slider_create(C);
214 ED_slider_factor_set(pso->slider, RNA_float_get(op->ptr, "factor"));
215
216 /* For each Pose-Channel which gets affected, get the F-Curves for that channel
217 * and set the relevant transform flags. */
220 params.object_mode = OB_MODE_POSE;
221 /* Explicitly setting this to false because we *do* want this to work for armature instances. */
222 params.no_dup_data = false;
225 pso->ob_data_array.reinitialize(objects.size());
226
227 for (const int ob_index : objects.index_range()) {
228 tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
229 Object *ob_iter = poseAnim_object_get(objects[ob_index]);
230
231 /* Ensure validity of the settings from the context. */
232 if (ob_iter == nullptr) {
233 continue;
234 }
235
236 ob_data->ob = ob_iter;
237 ob_data->valid = true;
238
239 /* Apply NLA mapping corrections so the frame look-ups work. */
241 ob_data->ob->adt, pso->prev_frame, NLATIME_CONVERT_UNMAP);
243 ob_data->ob->adt, pso->next_frame, NLATIME_CONVERT_UNMAP);
244
245 /* Set depsgraph flags. */
246 /* Make sure the lock is set OK, unlock can be accidentally saved? */
247 ob_data->ob->pose->flag |= POSE_LOCKED;
248 ob_data->ob->pose->flag &= ~POSE_DO_UNLOCK;
249 }
250
251 /* Do basic initialize of RB-BST used for finding keyframes, but leave the filling of it up
252 * to the caller of this (usually only invoke() will do it, to make things more efficient). */
253 pso->keylist = ED_keylist_create();
254
255 /* Initialize numeric input. */
256 initNumInput(&pso->num);
257 pso->num.idx_max = 0; /* One axis. */
258 pso->num.unit_type[0] = B_UNIT_NONE; /* Percentages don't have any units. */
259
260 if (pso->area && (pso->area->spacetype == SPACE_VIEW3D)) {
261 /* Save current bone visibility. */
262 View3D *v3d = static_cast<View3D *>(pso->area->spacedata.first);
263 pso->overlay_flag = v3d->overlay.flag;
264 }
265
266 /* Return status is whether we've got all the data we were requested to get. */
267 return 1;
268}
269
274{
275 tPoseSlideOp *pso = static_cast<tPoseSlideOp *>(op->customdata);
276
278
279 /* Hide Bone Overlay. */
280 if (pso->area && (pso->area->spacetype == SPACE_VIEW3D)) {
281 View3D *v3d = static_cast<View3D *>(pso->area->spacedata.first);
282 v3d->overlay.flag = pso->overlay_flag;
283 }
284
285 /* Free the temp pchan links and their data. */
287
288 /* Free RB-BST for keyframes (if it contained data). */
290
291 /* Free data itself. */
292 MEM_delete(pso);
293
294 /* Cleanup. */
295 op->customdata = nullptr;
296}
297
298/* ------------------------------------ */
299
304{
305 /* Wrapper around the generic version, allowing us to add some custom stuff later still. */
306 for (tPoseSlideObject &ob_data : pso->ob_data_array) {
307 if (ob_data.valid) {
308 poseAnim_mapping_refresh(C, pso->scene, ob_data.ob);
309 }
310 }
311}
312
318 Object *ob,
319 float *prev_frame,
320 float *next_frame)
321{
322 for (tPoseSlideObject &ob_data : pso->ob_data_array) {
323 Object *ob_iter = ob_data.ob;
324
325 if (ob_iter == ob) {
326 *prev_frame = ob_data.prev_frame;
327 *next_frame = ob_data.next_frame;
328 return true;
329 }
330 }
331 *prev_frame = *next_frame = 0.0f;
332 return false;
333}
334
338static void pose_slide_apply_val(tPoseSlideOp *pso, const FCurve *fcu, Object *ob, float *val)
339{
340 float prev_frame, next_frame;
341 float prev_weight, next_weight;
342 pose_frame_range_from_object_get(pso, ob, &prev_frame, &next_frame);
343
344 const float factor = ED_slider_factor_get(pso->slider);
345 const float current_frame = float(pso->current_frame);
346
347 /* Calculate the relative weights of the endpoints. */
348 if (pso->mode == POSESLIDE_BREAKDOWN) {
349 /* Get weights from the factor control. */
350 next_weight = factor;
351 prev_weight = 1.0f - next_weight;
352 }
353 else {
354 /* - these weights are derived from the relative distance of these
355 * poses from the current frame
356 * - they then get normalized so that they only sum up to 1
357 */
358
359 next_weight = current_frame - float(pso->prev_frame);
360 prev_weight = float(pso->next_frame) - current_frame;
361
362 const float total_weight = next_weight + prev_weight;
363 next_weight = (next_weight / total_weight);
364 prev_weight = (prev_weight / total_weight);
365 }
366
367 /* Get keyframe values for endpoint poses to blend with. */
368 /* Previous/start. */
369 const float prev_frame_y = evaluate_fcurve(fcu, prev_frame);
370 const float next_frame_y = evaluate_fcurve(fcu, next_frame);
371
372 /* Depending on the mode, calculate the new value. */
373 switch (pso->mode) {
374 case POSESLIDE_PUSH: /* Make the current pose more pronounced. */
375 {
376 /* Slide the pose away from the breakdown pose in the timeline */
377 (*val) -= ((prev_frame_y * prev_weight) + (next_frame_y * next_weight) - (*val)) * factor;
378 break;
379 }
380 case POSESLIDE_RELAX: /* Make the current pose more like its surrounding ones. */
381 {
382 /* Slide the pose towards the breakdown pose in the timeline */
383 (*val) += ((prev_frame_y * prev_weight) + (next_frame_y * next_weight) - (*val)) * factor;
384 break;
385 }
386 case POSESLIDE_BREAKDOWN: /* Make the current pose slide around between the endpoints. */
387 {
388 /* Perform simple linear interpolation. */
389 (*val) = interpf(next_frame_y, prev_frame_y, factor);
390 break;
391 }
392 case POSESLIDE_BLEND: /* Blend the current pose with the previous (<50%) or next key (>50%). */
393 {
394 const float current_frame_y = evaluate_fcurve(fcu, current_frame);
395 /* Convert factor to absolute 0-1 range which is needed for `interpf`. */
396 const float blend_factor = fabs((factor - 0.5f) * 2);
397
398 if (factor < 0.5) {
399 /* Blend to previous key. */
400 (*val) = interpf(prev_frame_y, current_frame_y, blend_factor);
401 }
402 else {
403 /* Blend to next key. */
404 (*val) = interpf(next_frame_y, current_frame_y, blend_factor);
405 }
406
407 break;
408 }
409 /* Those are handled in pose_slide_rest_pose_apply. */
411 break;
412 }
413 }
414}
415
420 tPChanFCurveLink *pfl,
421 float vec[3],
422 const char propName[])
423{
424 LinkData *ld = nullptr;
425 char *path = nullptr;
426
427 /* Get the path to use. */
428 path = BLI_sprintfN("%s.%s", pfl->pchan_path, propName);
429
430 /* Using this path, find each matching F-Curve for the variables we're interested in. */
431 while ((ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path))) {
432 FCurve *fcu = static_cast<FCurve *>(ld->data);
433 const int idx = fcu->array_index;
434 const int lock = pso->axislock;
435
436 /* Check if this F-Curve is ok given the current axis locks. */
437 BLI_assert(fcu->array_index < 3);
438
439 if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) ||
440 ((lock & PS_LOCK_Z) && (idx == 2)))
441 {
442 /* Just work on these channels one by one... there's no interaction between values. */
443 pose_slide_apply_val(pso, fcu, pfl->ob, &vec[fcu->array_index]);
444 }
445 }
446
447 /* Free the temp path we got. */
448 MEM_freeN(path);
449}
450
455 tPChanFCurveLink *pfl,
456 const char prop_prefix[])
457{
458 int len = strlen(pfl->pchan_path);
459
460 /* Setup pointer RNA for resolving paths. */
461 PointerRNA ptr = RNA_pointer_create_discrete(nullptr, &RNA_PoseBone, pfl->pchan);
462
463 /* - custom properties are just denoted using ["..."][etc.] after the end of the base path,
464 * so just check for opening pair after the end of the path
465 * - bbone properties are similar, but they always start with a prefix "bbone_*",
466 * so a similar method should work here for those too
467 */
468 LISTBASE_FOREACH (LinkData *, ld, &pfl->fcurves) {
469 FCurve *fcu = static_cast<FCurve *>(ld->data);
470 const char *bPtr, *pPtr;
471
472 if (fcu->rna_path == nullptr) {
473 continue;
474 }
475
476 /* Do we have a match?
477 * - bPtr is the RNA Path with the standard part chopped off.
478 * - pPtr is the chunk of the path which is left over.
479 */
480 bPtr = strstr(fcu->rna_path, pfl->pchan_path) + len;
481 pPtr = strstr(bPtr, prop_prefix);
482
483 if (pPtr) {
484 /* Use RNA to try and get a handle on this property, then, assuming that it is just
485 * numerical, try and grab the value as a float for temp editing before setting back. */
487
488 if (prop) {
489 switch (RNA_property_type(prop)) {
490 /* Continuous values that can be smoothly interpolated. */
491 case PROP_FLOAT: {
492 const bool is_array = RNA_property_array_check(prop);
493 float tval;
494 if (is_array) {
495 if (UNLIKELY(uint(fcu->array_index) >= RNA_property_array_length(&ptr, prop))) {
496 break; /* Out of range, skip. */
497 }
498 tval = RNA_property_float_get_index(&ptr, prop, fcu->array_index);
499 }
500 else {
501 tval = RNA_property_float_get(&ptr, prop);
502 }
503
504 pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
505
506 if (is_array) {
507 RNA_property_float_set_index(&ptr, prop, fcu->array_index, tval);
508 }
509 else {
510 RNA_property_float_set(&ptr, prop, tval);
511 }
512 break;
513 }
514 case PROP_INT: {
515 const bool is_array = RNA_property_array_check(prop);
516 float tval;
517 if (is_array) {
518 if (UNLIKELY(uint(fcu->array_index) >= RNA_property_array_length(&ptr, prop))) {
519 break; /* Out of range, skip. */
520 }
521 tval = RNA_property_int_get_index(&ptr, prop, fcu->array_index);
522 }
523 else {
524 tval = RNA_property_int_get(&ptr, prop);
525 }
526
527 pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
528
529 if (is_array) {
530 RNA_property_int_set_index(&ptr, prop, fcu->array_index, tval);
531 }
532 else {
533 RNA_property_int_set(&ptr, prop, tval);
534 }
535 break;
536 }
537
538 /* Values which can only take discrete values. */
539 case PROP_BOOLEAN: {
540 const bool is_array = RNA_property_array_check(prop);
541 float tval;
542 if (is_array) {
543 if (UNLIKELY(uint(fcu->array_index) >= RNA_property_array_length(&ptr, prop))) {
544 break; /* Out of range, skip. */
545 }
546 tval = float(RNA_property_boolean_get_index(&ptr, prop, fcu->array_index));
547 }
548 else {
549 tval = float(RNA_property_boolean_get(&ptr, prop));
550 }
551
552 pose_slide_apply_val(pso, fcu, pfl->ob, &tval);
553
554 /* XXX: do we need threshold clamping here? */
555 if (is_array) {
557 }
558 else {
559 RNA_property_boolean_set(&ptr, prop, tval);
560 }
561 break;
562 }
563 case PROP_ENUM: {
564 /* Don't handle this case - these don't usually represent interchangeable
565 * set of values which should be interpolated between. */
566 break;
567 }
568
569 default:
570 /* Cannot handle. */
571 // printf("Cannot Pose Slide non-numerical property\n");
572 break;
573 }
574 }
575 }
576 }
577}
578
583{
584 const FCurve *fcu_w = nullptr, *fcu_x = nullptr, *fcu_y = nullptr, *fcu_z = nullptr;
585 bPoseChannel *pchan = pfl->pchan;
586 LinkData *ld = nullptr;
587 char *path = nullptr;
588 float prev_frame, next_frame;
589
590 if (!pose_frame_range_from_object_get(pso, pfl->ob, &prev_frame, &next_frame)) {
591 BLI_assert_msg(0, "Invalid pfl data");
592 return;
593 }
594
595 /* Get the path to use - this should be quaternion rotations only (needs care). */
596 path = BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation_quaternion");
597
598 /* Get the current frame number. */
599 const float current_frame = float(pso->current_frame);
600 const float factor = ED_slider_factor_get(pso->slider);
601
602 /* Using this path, find each matching F-Curve for the variables we're interested in. */
603 while ((ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path))) {
604 FCurve *fcu = static_cast<FCurve *>(ld->data);
605
606 /* Assign this F-Curve to one of the relevant pointers. */
607 switch (fcu->array_index) {
608 case 3: /* z */
609 fcu_z = fcu;
610 break;
611 case 2: /* y */
612 fcu_y = fcu;
613 break;
614 case 1: /* x */
615 fcu_x = fcu;
616 break;
617 case 0: /* w */
618 fcu_w = fcu;
619 break;
620 }
621 }
622
623 /* Only if all channels exist, proceed. */
624 if (fcu_w && fcu_x && fcu_y && fcu_z) {
625 float quat_final[4];
626
627 /* Perform blending. */
629 float quat_prev[4], quat_next[4];
630
631 quat_prev[0] = evaluate_fcurve(fcu_w, prev_frame);
632 quat_prev[1] = evaluate_fcurve(fcu_x, prev_frame);
633 quat_prev[2] = evaluate_fcurve(fcu_y, prev_frame);
634 quat_prev[3] = evaluate_fcurve(fcu_z, prev_frame);
635
636 quat_next[0] = evaluate_fcurve(fcu_w, next_frame);
637 quat_next[1] = evaluate_fcurve(fcu_x, next_frame);
638 quat_next[2] = evaluate_fcurve(fcu_y, next_frame);
639 quat_next[3] = evaluate_fcurve(fcu_z, next_frame);
640
641 normalize_qt(quat_prev);
642 normalize_qt(quat_next);
643
644 if (pso->mode == POSESLIDE_BREAKDOWN) {
645 /* Just perform the interpolation between quat_prev and
646 * quat_next using pso->factor as a guide. */
647 interp_qt_qtqt(quat_final, quat_prev, quat_next, factor);
648 }
649 else {
650 float quat_curr[4], quat_breakdown[4];
651
652 normalize_qt_qt(quat_curr, pchan->quat);
653
654 /* Compute breakdown based on actual frame range. */
655 const float interp_factor = (current_frame - pso->prev_frame) /
656 float(pso->next_frame - pso->prev_frame);
657
658 interp_qt_qtqt(quat_breakdown, quat_prev, quat_next, interp_factor);
659
660 if (pso->mode == POSESLIDE_PUSH) {
661 interp_qt_qtqt(quat_final, quat_breakdown, quat_curr, 1.0f + factor);
662 }
663 else {
665 interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, factor);
666 }
667 }
668 }
669 else if (pso->mode == POSESLIDE_BLEND) {
670 float quat_blend[4];
671 float quat_curr[4];
672
673 copy_qt_qt(quat_curr, pchan->quat);
674
675 if (factor < 0.5) {
676 quat_blend[0] = evaluate_fcurve(fcu_w, prev_frame);
677 quat_blend[1] = evaluate_fcurve(fcu_x, prev_frame);
678 quat_blend[2] = evaluate_fcurve(fcu_y, prev_frame);
679 quat_blend[3] = evaluate_fcurve(fcu_z, prev_frame);
680 }
681 else {
682 quat_blend[0] = evaluate_fcurve(fcu_w, next_frame);
683 quat_blend[1] = evaluate_fcurve(fcu_x, next_frame);
684 quat_blend[2] = evaluate_fcurve(fcu_y, next_frame);
685 quat_blend[3] = evaluate_fcurve(fcu_z, next_frame);
686 }
687
688 normalize_qt(quat_blend);
689 normalize_qt(quat_curr);
690
691 const float blend_factor = fabs((factor - 0.5f) * 2);
692
693 interp_qt_qtqt(quat_final, quat_curr, quat_blend, blend_factor);
694 }
695
696 /* Apply final to the pose bone, keeping compatible for similar keyframe positions. */
697 quat_to_compatible_quat(pchan->quat, quat_final, pchan->quat);
698 }
699
700 /* Free the path now. */
701 MEM_freeN(path);
702}
703
704static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], float default_value)
705{
706 /* We only slide to the rest pose. So only use the default rest pose value. */
707 const int lock = pso->axislock;
708 const float factor = ED_slider_factor_get(pso->slider);
709 for (int idx = 0; idx < 3; idx++) {
710 if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) ||
711 ((lock & PS_LOCK_Z) && (idx == 2)))
712 {
713 float diff_val = default_value - vec[idx];
714 vec[idx] += factor * diff_val;
715 }
716 }
717}
718
719static void pose_slide_rest_pose_apply_other_rot(tPoseSlideOp *pso, float vec[4], bool quat)
720{
721 /* We only slide to the rest pose. So only use the default rest pose value. */
722 float default_values[] = {1.0f, 0.0f, 0.0f, 0.0f};
723 if (!quat) {
724 /* Axis Angle */
725 default_values[0] = 0.0f;
726 default_values[2] = 1.0f;
727 }
728 const float factor = ED_slider_factor_get(pso->slider);
729 for (int idx = 0; idx < 4; idx++) {
730 float diff_val = default_values[idx] - vec[idx];
731 vec[idx] += factor * diff_val;
732 }
733}
734
739{
740 /* For each link, handle each set of transforms. */
742 /* Valid transforms for each #bPoseChannel should have been noted already.
743 * - Sliding the pose should be a straightforward exercise for location+rotation,
744 * but rotations get more complicated since we may want to use quaternion blending
745 * for quaternions instead.
746 */
747 bPoseChannel *pchan = pfl->pchan;
748
749 if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) {
750 /* Calculate these for the 'location' vector, and use location curves. */
751 pose_slide_rest_pose_apply_vec3(pso, pchan->loc, 0.0f);
752 }
753
754 if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SCALE) && (pchan->flag & POSE_SCALE)) {
755 /* Calculate these for the 'scale' vector, and use scale curves. */
756 pose_slide_rest_pose_apply_vec3(pso, pchan->scale, 1.0f);
757 }
758
759 if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) {
760 /* Everything depends on the rotation mode. */
761 if (pchan->rotmode > 0) {
762 /* Eulers - so calculate these for the 'eul' vector, and use euler_rotation curves. */
763 pose_slide_rest_pose_apply_vec3(pso, pchan->eul, 0.0f);
764 }
765 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
766 pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, false);
767 }
768 else {
769 /* Quaternions - use quaternion blending. */
771 }
772 }
773
775 /* Bbone properties - they all start a "bbone_" prefix. */
776 /* TODO: Not implemented. */
777 // pose_slide_apply_props(pso, pfl, "bbone_");
778 }
779
780 if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
781 /* Not strictly a transform, but custom properties contribute
782 * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */
783 /* TODO: Not implemented. */
784 // pose_slide_apply_props(pso, pfl, "[\"");
785 }
786 }
787
788 /* Depsgraph updates + redraws. */
789 pose_slide_refresh(C, pso);
790}
791
796{
797 /* Sanitize the frame ranges. */
798 if (pso->prev_frame == pso->next_frame) {
799 /* Move out one step either side. */
800 pso->prev_frame--;
801 pso->next_frame++;
802
803 for (tPoseSlideObject &ob_data : pso->ob_data_array) {
804 if (!ob_data.valid) {
805 continue;
806 }
807
808 /* Apply NLA mapping corrections so the frame look-ups work. */
810 ob_data.ob->adt, pso->prev_frame, NLATIME_CONVERT_UNMAP);
812 ob_data.ob->adt, pso->next_frame, NLATIME_CONVERT_UNMAP);
813 }
814 }
815
816 /* For each link, handle each set of transforms. */
818 /* Valid transforms for each #bPoseChannel should have been noted already
819 * - sliding the pose should be a straightforward exercise for location+rotation,
820 * but rotations get more complicated since we may want to use quaternion blending
821 * for quaternions instead...
822 */
823 bPoseChannel *pchan = pfl->pchan;
824
825 if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) {
826 /* Calculate these for the 'location' vector, and use location curves. */
827 pose_slide_apply_vec3(pso, pfl, pchan->loc, "location");
828 }
829
830 if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SCALE) && (pchan->flag & POSE_SCALE)) {
831 /* Calculate these for the 'scale' vector, and use scale curves. */
832 pose_slide_apply_vec3(pso, pfl, pchan->scale, "scale");
833 }
834
835 if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) {
836 /* Everything depends on the rotation mode. */
837 if (pchan->rotmode > 0) {
838 /* Eulers - so calculate these for the 'eul' vector, and use euler_rotation curves. */
839 pose_slide_apply_vec3(pso, pfl, pchan->eul, "rotation_euler");
840 }
841 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
842 /* TODO: need to figure out how to do this! */
843 }
844 else {
845 /* Quaternions - use quaternion blending. */
846 pose_slide_apply_quat(pso, pfl);
847 }
848 }
849
851 /* Bbone properties - they all start a "bbone_" prefix. */
852 pose_slide_apply_props(pso, pfl, "bbone_");
853 }
854
855 if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
856 /* Not strictly a transform, but custom properties contribute
857 * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */
858 pose_slide_apply_props(pso, pfl, "[\"");
859 }
860 }
861
862 /* Depsgraph updates + redraws. */
863 pose_slide_refresh(C, pso);
864}
865
870{
871 /* Wrapper around the generic call. */
872 poseAnim_mapping_autoKeyframe(C, pso->scene, &pso->pfLinks, float(pso->current_frame));
873}
874
879{
880 /* Wrapper around the generic call, so that custom stuff can be added later. */
882}
883
884/* ------------------------------------ */
885
892{
893 const char *mode_st;
894 switch (pso->mode) {
895 case POSESLIDE_PUSH:
896 mode_st = IFACE_("Push Pose");
897 break;
898 case POSESLIDE_RELAX:
899 mode_st = IFACE_("Relax Pose");
900 break;
902 mode_st = IFACE_("Breakdown");
903 break;
904 case POSESLIDE_BLEND:
905 mode_st = IFACE_("Blend to Neighbor");
906 break;
907 default:
908 /* Unknown. */
909 mode_st = IFACE_("Sliding-Tool");
910 break;
911 }
912
914
915 WorkspaceStatus status(C);
916
917 status.item(IFACE_("Confirm"), ICON_MOUSE_LMB);
918 status.item(IFACE_("Cancel"), ICON_EVENT_ESC);
919 status.item(IFACE_("Adjust"), ICON_MOUSE_MOVE);
920
921 status.item_bool("", pso->channels == PS_TFM_LOC, ICON_EVENT_G);
922 status.item_bool("", pso->channels == PS_TFM_ROT, ICON_EVENT_R);
923 status.item_bool("", pso->channels == PS_TFM_SCALE, ICON_EVENT_S);
924 status.item_bool("", pso->channels == PS_TFM_BBONE_SHAPE, ICON_EVENT_B);
925 status.item_bool("", pso->channels == PS_TFM_PROPS, ICON_EVENT_C);
926
927 switch (pso->channels) {
928 case PS_TFM_LOC:
929 status.item("Location Only", ICON_NONE);
930 break;
931 case PS_TFM_ROT:
932 status.item("Rotation Only", ICON_NONE);
933 break;
934 case PS_TFM_SCALE:
935 status.item("Scale Only", ICON_NONE);
936 break;
938 status.item("Bendy Bones Only", ICON_NONE);
939 break;
940 case PS_TFM_PROPS:
941 status.item("Custom Properties Only", ICON_NONE);
942 break;
943 default:
944 status.item("Transform limits", ICON_NONE);
945 break;
946 }
947
949 status.item_bool("", pso->axislock & PS_LOCK_X, ICON_EVENT_X);
950 status.item_bool("", pso->axislock & PS_LOCK_Y, ICON_EVENT_Y);
951 status.item_bool("", pso->axislock & PS_LOCK_Z, ICON_EVENT_Z);
952 status.item(pso->axislock == 0 ? IFACE_("Axis Constraint") : IFACE_("Axis Only"), ICON_NONE);
953 }
954
955 if (hasNumInput(&pso->num)) {
956 Scene *scene = pso->scene;
957 char str_offs[NUM_STR_REP_LEN];
958
959 outputNumInput(&pso->num, str_offs, scene->unit);
960
961 status.item(str_offs, ICON_NONE);
962 }
963 else if (pso->area && (pso->area->spacetype == SPACE_VIEW3D)) {
964 ED_slider_status_get(pso->slider, status);
965 View3D *v3d = static_cast<View3D *>(pso->area->spacedata.first);
966 status.item_bool(
967 IFACE_("Bone Visibility"), !(v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES), ICON_EVENT_H);
968 }
969}
970
975{
976 wmWindow *win = CTX_wm_window(C);
977
978 tPoseSlideOp *pso = static_cast<tPoseSlideOp *>(op->customdata);
979
980 ED_slider_init(pso->slider, event);
981
982 /* For each link, add all its keyframes to the search tree. */
984 /* Do this for each F-Curve. */
985 LISTBASE_FOREACH (LinkData *, ld, &pfl->fcurves) {
986 AnimData *adt = pfl->ob->adt;
987 FCurve *fcu = static_cast<FCurve *>(ld->data);
988 fcurve_to_keylist(adt, fcu, pso->keylist, 0, {-FLT_MAX, FLT_MAX}, adt != nullptr);
989 }
990 }
991
992 /* Cancel if no keyframes found. */
994 if (ED_keylist_is_empty(pso->keylist)) {
995 BKE_report(op->reports, RPT_ERROR, "No keyframes to slide between");
996 pose_slide_exit(C, op);
997 return OPERATOR_CANCELLED;
998 }
999
1000 float current_frame = float(pso->current_frame);
1001
1002 /* Firstly, check if the current frame is a keyframe. */
1003 const ActKeyColumn *ak = ED_keylist_find_exact(pso->keylist, current_frame);
1004
1005 if (ak == nullptr) {
1006 /* Current frame is not a keyframe, so search. */
1007 const ActKeyColumn *pk = ED_keylist_find_prev(pso->keylist, current_frame);
1008 const ActKeyColumn *nk = ED_keylist_find_next(pso->keylist, current_frame);
1009
1010 /* New set the frames. */
1011 /* Previous frame. */
1012 pso->prev_frame = (pk) ? (pk->cfra) : (pso->current_frame - 1);
1013 RNA_int_set(op->ptr, "prev_frame", pso->prev_frame);
1014 /* Next frame. */
1015 pso->next_frame = (nk) ? (nk->cfra) : (pso->current_frame + 1);
1016 RNA_int_set(op->ptr, "next_frame", pso->next_frame);
1017 }
1018 else {
1019 /* Current frame itself is a keyframe, so just take keyframes on either side. */
1020 /* Previous frame. */
1021 pso->prev_frame = (ak->prev) ? (ak->prev->cfra) : (pso->current_frame - 1);
1022 RNA_int_set(op->ptr, "prev_frame", pso->prev_frame);
1023 /* Next frame. */
1024 pso->next_frame = (ak->next) ? (ak->next->cfra) : (pso->current_frame + 1);
1025 RNA_int_set(op->ptr, "next_frame", pso->next_frame);
1026 }
1027
1028 /* Apply NLA mapping corrections so the frame look-ups work. */
1029 for (tPoseSlideObject &ob_data : pso->ob_data_array) {
1030 if (ob_data.valid) {
1032 ob_data.ob->adt, pso->prev_frame, NLATIME_CONVERT_UNMAP);
1034 ob_data.ob->adt, pso->next_frame, NLATIME_CONVERT_UNMAP);
1035 }
1036 }
1037
1038 /* Initial apply for operator. */
1039 /* TODO: need to calculate factor for initial round too. */
1040 if (!ELEM(pso->mode, POSESLIDE_BLEND_REST)) {
1041 pose_slide_apply(C, pso);
1042 }
1043 else {
1045 }
1046
1047 /* Depsgraph updates + redraws. */
1048 pose_slide_refresh(C, pso);
1049
1050 /* Set cursor to indicate modal. */
1052
1053 /* Header print. */
1055
1056 /* Add a modal handler for this operator. */
1058
1060}
1061
1066 tPoseSlideOp *pso,
1067 ePoseSlide_Channels channel)
1068{
1069 /* Turn channel on or off? */
1070 if (pso->channels == channel) {
1071 /* Already limiting to transform only, so pressing this again turns it off */
1072 pso->channels = PS_TFM_ALL;
1073 }
1074 else {
1075 /* Only this set of channels */
1076 pso->channels = channel;
1077 }
1078 RNA_enum_set(op->ptr, "channels", pso->channels);
1079
1080 /* Reset axis limits too for good measure */
1081 pso->axislock = ePoseSlide_AxisLock(0);
1082 RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
1083}
1084
1089 tPoseSlideOp *pso,
1091{
1092 /* Axis can only be set when a transform is set - it doesn't make sense otherwise */
1094 pso->axislock = ePoseSlide_AxisLock(0);
1095 RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
1096 return false;
1097 }
1098
1099 /* Turn on or off? */
1100 if (pso->axislock == axis) {
1101 /* Already limiting on this axis, so turn off */
1102 pso->axislock = ePoseSlide_AxisLock(0);
1103 }
1104 else {
1105 /* Only this axis */
1106 pso->axislock = axis;
1107 }
1108 RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
1109
1110 /* Setting changed, so pose update is needed */
1111 return true;
1112}
1113
1118{
1119 tPoseSlideOp *pso = static_cast<tPoseSlideOp *>(op->customdata);
1120 wmWindow *win = CTX_wm_window(C);
1121 bool do_pose_update = false;
1122
1123 const bool has_numinput = hasNumInput(&pso->num);
1124
1125 do_pose_update = ED_slider_modal(pso->slider, event);
1126
1127 switch (event->type) {
1128 case LEFTMOUSE: /* Confirm. */
1129 case EVT_RETKEY:
1130 case EVT_PADENTER: {
1131 if (event->val == KM_PRESS) {
1132 /* Return to normal cursor and header status. */
1133 ED_workspace_status_text(C, nullptr);
1135
1136 /* Depsgraph updates + redraws. Redraw needed to remove UI. */
1137 pose_slide_refresh(C, pso);
1138
1139 /* Insert keyframes as required. */
1141 pose_slide_exit(C, op);
1142
1143 /* Done! */
1144 return OPERATOR_FINISHED;
1145 }
1146 break;
1147 }
1148
1149 case EVT_ESCKEY: /* Cancel. */
1150 case RIGHTMOUSE: {
1151 if (event->val == KM_PRESS) {
1152 /* Return to normal cursor and header status. */
1153 ED_workspace_status_text(C, nullptr);
1155
1156 /* Reset transforms back to original state. */
1157 pose_slide_reset(pso);
1158
1159 /* Depsgraph updates + redraws. */
1160 pose_slide_refresh(C, pso);
1161
1162 /* Clean up temp data. */
1163 pose_slide_exit(C, op);
1164
1165 /* Canceled! */
1166 return OPERATOR_CANCELLED;
1167 }
1168 break;
1169 }
1170
1171 /* Factor Change... */
1172 case MOUSEMOVE: /* Calculate new position. */
1173 {
1174 /* Only handle mouse-move if not doing numinput. */
1175 if (has_numinput == false) {
1176 /* Update pose to reflect the new values (see below). */
1177 do_pose_update = true;
1178 }
1179 break;
1180 }
1181 default: {
1182 if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) {
1183 float value;
1184
1185 /* Grab percentage from numeric input, and store this new value for redo
1186 * NOTE: users see ints, while internally we use a 0-1 float
1187 */
1188 value = ED_slider_factor_get(pso->slider) * 100.0f;
1189 applyNumInput(&pso->num, &value);
1190
1191 float factor = value / 100;
1192 ED_slider_factor_set(pso->slider, factor);
1193 RNA_float_set(op->ptr, "factor", ED_slider_factor_get(pso->slider));
1194
1195 /* Update pose to reflect the new values (see below) */
1196 do_pose_update = true;
1197 break;
1198 }
1199 if (event->val == KM_PRESS) {
1200 switch (event->type) {
1201 /* Transform Channel Limits. */
1202 /* XXX: Replace these hard-coded hotkeys with a modal-map that can be customized. */
1203 case EVT_GKEY: /* Location */
1204 {
1206 do_pose_update = true;
1207 break;
1208 }
1209 case EVT_RKEY: /* Rotation */
1210 {
1212 do_pose_update = true;
1213 break;
1214 }
1215 case EVT_SKEY: /* Scale */
1216 {
1218 do_pose_update = true;
1219 break;
1220 }
1221 case EVT_BKEY: /* Bendy Bones */
1222 {
1224 do_pose_update = true;
1225 break;
1226 }
1227 case EVT_CKEY: /* Custom Properties */
1228 {
1230 do_pose_update = true;
1231 break;
1232 }
1233
1234 /* Axis Locks */
1235 /* XXX: Hardcoded... */
1236 case EVT_XKEY: {
1238 do_pose_update = true;
1239 }
1240 break;
1241 }
1242 case EVT_YKEY: {
1244 do_pose_update = true;
1245 }
1246 break;
1247 }
1248 case EVT_ZKEY: {
1250 do_pose_update = true;
1251 }
1252 break;
1253 }
1254
1255 /* Toggle Bone visibility. */
1256 case EVT_HKEY: {
1257 if (pso->area && (pso->area->spacetype == SPACE_VIEW3D)) {
1258 View3D *v3d = static_cast<View3D *>(pso->area->spacedata.first);
1261 }
1262 break;
1263 }
1264
1265 default: /* Some other unhandled key... */
1266 break;
1267 }
1268 }
1269 else {
1270 /* Unhandled event - maybe it was some view manipulation? */
1271 /* Allow to pass through. */
1273 }
1274 }
1275 }
1276
1277 /* Perform pose updates - in response to some user action
1278 * (e.g. pressing a key or moving the mouse). */
1279 if (do_pose_update) {
1280 RNA_float_set(op->ptr, "factor", ED_slider_factor_get(pso->slider));
1281
1282 /* Update percentage indicator in header. */
1284
1285 /* Reset transforms (to avoid accumulation errors). */
1286 pose_slide_reset(pso);
1287
1288 /* Apply. */
1289 if (!ELEM(pso->mode, POSESLIDE_BLEND_REST)) {
1290 pose_slide_apply(C, pso);
1291 }
1292 else {
1294 }
1295 }
1296
1297 /* Still running. */
1299}
1300
1305{
1306 /* Cleanup and done. */
1307 pose_slide_exit(C, op);
1308}
1309
1314{
1315 /* Settings should have been set up ok for applying, so just apply! */
1316 if (!ELEM(pso->mode, POSESLIDE_BLEND_REST)) {
1317 pose_slide_apply(C, pso);
1318 }
1319 else {
1321 }
1322
1323 /* Insert keyframes if needed. */
1325
1326 /* Cleanup and done. */
1327 pose_slide_exit(C, op);
1328
1329 return OPERATOR_FINISHED;
1330}
1331
1336{
1337 PropertyRNA *prop;
1338
1339 prop = RNA_def_float_factor(ot->srna,
1340 "factor",
1341 0.5f,
1342 0.0f,
1343 1.0f,
1344 "Factor",
1345 "Weighting factor for which keyframe is favored more",
1346 0.0,
1347 1.0);
1349
1350 prop = RNA_def_int(ot->srna,
1351 "prev_frame",
1352 0,
1353 MINAFRAME,
1354 MAXFRAME,
1355 "Previous Keyframe",
1356 "Frame number of keyframe immediately before the current frame",
1357 0,
1358 50);
1360
1361 prop = RNA_def_int(ot->srna,
1362 "next_frame",
1363 0,
1364 MINAFRAME,
1365 MAXFRAME,
1366 "Next Keyframe",
1367 "Frame number of keyframe immediately after the current frame",
1368 0,
1369 50);
1371
1372 prop = RNA_def_enum(ot->srna,
1373 "channels",
1375 PS_TFM_ALL,
1376 "Channels",
1377 "Set of properties that are affected");
1379 prop = RNA_def_enum(ot->srna,
1380 "axis_lock",
1382 0,
1383 "Axis Lock",
1384 "Transform axis to restrict effects to");
1386}
1387
1388/* ------------------------------------ */
1389
1394{
1395 /* Initialize data. */
1396 if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
1397 pose_slide_exit(C, op);
1398 return OPERATOR_CANCELLED;
1399 }
1400
1401 /* Do common setup work. */
1402 return pose_slide_invoke_common(C, op, event);
1403}
1404
1409{
1410 tPoseSlideOp *pso;
1411
1412 /* Initialize data (from RNA-props). */
1413 if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) {
1414 pose_slide_exit(C, op);
1415 return OPERATOR_CANCELLED;
1416 }
1417
1418 pso = static_cast<tPoseSlideOp *>(op->customdata);
1419
1420 /* Do common exec work. */
1421 return pose_slide_exec_common(C, op, pso);
1422}
1423
1425{
1426 /* identifiers */
1427 ot->name = "Push Pose from Breakdown";
1428 ot->idname = "POSE_OT_push";
1429 ot->description = "Exaggerate the current pose in regards to the breakdown pose";
1430
1431 /* callbacks */
1432 ot->exec = pose_slide_push_exec;
1433 ot->invoke = pose_slide_push_invoke;
1434 ot->modal = pose_slide_modal;
1435 ot->cancel = pose_slide_cancel;
1436 ot->poll = ED_operator_posemode;
1437
1438 /* flags */
1440
1441 /* Properties */
1443}
1444
1445/* ........................ */
1446
1451{
1452 /* Initialize data. */
1453 if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
1454 pose_slide_exit(C, op);
1455 return OPERATOR_CANCELLED;
1456 }
1457
1458 /* Do common setup work. */
1459 return pose_slide_invoke_common(C, op, event);
1460}
1461
1466{
1467 tPoseSlideOp *pso;
1468
1469 /* Initialize data (from RNA-props). */
1470 if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) {
1471 pose_slide_exit(C, op);
1472 return OPERATOR_CANCELLED;
1473 }
1474
1475 pso = static_cast<tPoseSlideOp *>(op->customdata);
1476
1477 /* Do common exec work. */
1478 return pose_slide_exec_common(C, op, pso);
1479}
1480
1482{
1483 /* identifiers */
1484 ot->name = "Relax Pose to Breakdown";
1485 ot->idname = "POSE_OT_relax";
1486 ot->description = "Make the current pose more similar to its breakdown pose";
1487
1488 /* callbacks */
1489 ot->exec = pose_slide_relax_exec;
1490 ot->invoke = pose_slide_relax_invoke;
1491 ot->modal = pose_slide_modal;
1492 ot->cancel = pose_slide_cancel;
1493 ot->poll = ED_operator_posemode;
1494
1495 /* flags */
1497
1498 /* Properties */
1500}
1501
1502/* ........................ */
1507 wmOperator *op,
1508 const wmEvent *event)
1509{
1510 /* Initialize data. */
1511 if (pose_slide_init(C, op, POSESLIDE_BLEND_REST) == 0) {
1512 pose_slide_exit(C, op);
1513 return OPERATOR_CANCELLED;
1514 }
1515
1516 tPoseSlideOp *pso = static_cast<tPoseSlideOp *>(op->customdata);
1519
1520 /* do common setup work */
1521 return pose_slide_invoke_common(C, op, event);
1522}
1523
1528{
1529 tPoseSlideOp *pso;
1530
1531 /* Initialize data (from RNA-props). */
1532 if (pose_slide_init(C, op, POSESLIDE_BLEND_REST) == 0) {
1533 pose_slide_exit(C, op);
1534 return OPERATOR_CANCELLED;
1535 }
1536
1537 pso = static_cast<tPoseSlideOp *>(op->customdata);
1538
1539 /* Do common exec work. */
1540 return pose_slide_exec_common(C, op, pso);
1541}
1542
1544{
1545 /* identifiers */
1546 ot->name = "Blend Pose with Rest Pose";
1547 ot->idname = "POSE_OT_blend_with_rest";
1548 ot->description = "Make the current pose more similar to, or further away from, the rest pose";
1549
1550 /* callbacks */
1553 ot->modal = pose_slide_modal;
1554 ot->cancel = pose_slide_cancel;
1555 ot->poll = ED_operator_posemode;
1556
1557 /* flags */
1559
1560 /* Properties */
1562}
1563
1564/* ........................ */
1565
1570 wmOperator *op,
1571 const wmEvent *event)
1572{
1573 /* Initialize data. */
1574 if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
1575 pose_slide_exit(C, op);
1576 return OPERATOR_CANCELLED;
1577 }
1578
1579 /* Do common setup work. */
1580 return pose_slide_invoke_common(C, op, event);
1581}
1582
1587{
1588 tPoseSlideOp *pso;
1589
1590 /* Initialize data (from RNA-props). */
1591 if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) {
1592 pose_slide_exit(C, op);
1593 return OPERATOR_CANCELLED;
1594 }
1595
1596 pso = static_cast<tPoseSlideOp *>(op->customdata);
1597
1598 /* Do common exec work. */
1599 return pose_slide_exec_common(C, op, pso);
1600}
1601
1603{
1604 /* identifiers */
1605 ot->name = "Pose Breakdowner";
1606 ot->idname = "POSE_OT_breakdown";
1607 ot->description = "Create a suitable breakdown pose on the current frame";
1608
1609 /* callbacks */
1612 ot->modal = pose_slide_modal;
1613 ot->cancel = pose_slide_cancel;
1614 ot->poll = ED_operator_posemode;
1615
1616 /* flags */
1618
1619 /* Properties */
1621}
1622
1623/* ........................ */
1625 wmOperator *op,
1626 const wmEvent *event)
1627{
1628 /* Initialize data. */
1629 if (pose_slide_init(C, op, POSESLIDE_BLEND) == 0) {
1630 pose_slide_exit(C, op);
1631 return OPERATOR_CANCELLED;
1632 }
1633
1634 /* Do common setup work. */
1635 return pose_slide_invoke_common(C, op, event);
1636}
1637
1639{
1640 tPoseSlideOp *pso;
1641
1642 /* Initialize data (from RNA-props). */
1643 if (pose_slide_init(C, op, POSESLIDE_BLEND) == 0) {
1644 pose_slide_exit(C, op);
1645 return OPERATOR_CANCELLED;
1646 }
1647
1648 pso = static_cast<tPoseSlideOp *>(op->customdata);
1649
1650 /* Do common exec work. */
1651 return pose_slide_exec_common(C, op, pso);
1652}
1653
1655{
1656 /* Identifiers. */
1657 ot->name = "Blend to Neighbor";
1658 ot->idname = "POSE_OT_blend_to_neighbor";
1659 ot->description = "Blend from current position to previous or next keyframe";
1660
1661 /* Callbacks. */
1664 ot->modal = pose_slide_modal;
1665 ot->cancel = pose_slide_cancel;
1666 ot->poll = ED_operator_posemode;
1667
1668 /* Flags. */
1670
1671 /* Properties. */
1673}
1674
1675/* **************************************************** */
1676/* B) Pose Propagate */
1677
1678/* "termination conditions" - i.e. when we stop */
1694
1695/* --------------------------------- */
1696
1699 float frame;
1700};
1701
1702static void propagate_curve_values(ListBase /*tPChanFCurveLink*/ *pflinks,
1703 const float source_frame,
1704 ListBase /*FrameLink*/ *target_frames)
1705{
1706 using namespace blender::animrig;
1707 const KeyframeSettings settings = get_keyframe_settings(true);
1708 LISTBASE_FOREACH (tPChanFCurveLink *, pfl, pflinks) {
1709 LISTBASE_FOREACH (LinkData *, ld, &pfl->fcurves) {
1710 FCurve *fcu = static_cast<FCurve *>(ld->data);
1711 if (!fcu->bezt) {
1712 continue;
1713 }
1714 const float current_fcu_value = evaluate_fcurve(fcu, source_frame);
1715 LISTBASE_FOREACH (FrameLink *, target_frame, target_frames) {
1717 fcu, {target_frame->frame, current_fcu_value}, settings, INSERTKEY_NOFLAGS);
1718 }
1719 }
1720 }
1721}
1722
1723static float find_next_key(ListBase *pflinks, const float start_frame)
1724{
1725 float target_frame = FLT_MAX;
1726 LISTBASE_FOREACH (tPChanFCurveLink *, pfl, pflinks) {
1727 LISTBASE_FOREACH (LinkData *, ld, &pfl->fcurves) {
1728 FCurve *fcu = static_cast<FCurve *>(ld->data);
1729 if (!fcu->bezt) {
1730 continue;
1731 }
1732 bool replace;
1733 int current_frame_index = BKE_fcurve_bezt_binarysearch_index(
1734 fcu->bezt, start_frame, fcu->totvert, &replace);
1735 if (replace) {
1736 current_frame_index += 1;
1737 }
1738 const int bezt_index = min_ii(current_frame_index, fcu->totvert - 1);
1739 target_frame = min_ff(target_frame, fcu->bezt[bezt_index].vec[1][0]);
1740 }
1741 }
1742
1743 return target_frame;
1744}
1745
1746static float find_last_key(ListBase *pflinks)
1747{
1748 float target_frame = FLT_MIN;
1749 LISTBASE_FOREACH (tPChanFCurveLink *, pfl, pflinks) {
1750 LISTBASE_FOREACH (LinkData *, ld, &pfl->fcurves) {
1751 const FCurve *fcu = static_cast<const FCurve *>(ld->data);
1752 if (!fcu->bezt) {
1753 continue;
1754 }
1755 target_frame = max_ff(target_frame, fcu->bezt[fcu->totvert - 1].vec[1][0]);
1756 }
1757 }
1758
1759 return target_frame;
1760}
1761
1762static void get_selected_marker_positions(Scene *scene, ListBase /*FrameLink*/ *target_frames)
1763{
1764 ListBase selected_markers = {nullptr, nullptr};
1765 ED_markers_make_cfra_list(&scene->markers, &selected_markers, true);
1766 LISTBASE_FOREACH (CfraElem *, marker, &selected_markers) {
1767 FrameLink *link = MEM_callocN<FrameLink>("Marker Key Link");
1768 link->frame = marker->cfra;
1769 BLI_addtail(target_frames, link);
1770 }
1771 BLI_freelistN(&selected_markers);
1772}
1773
1775 const float start_frame,
1776 const float end_frame,
1777 ListBase /*FrameLink*/ *target_frames)
1778{
1779 AnimKeylist *keylist = ED_keylist_create();
1780 LISTBASE_FOREACH (tPChanFCurveLink *, pfl, pflinks) {
1781 LISTBASE_FOREACH (LinkData *, ld, &pfl->fcurves) {
1782 FCurve *fcu = static_cast<FCurve *>(ld->data);
1783 fcurve_to_keylist(nullptr, fcu, keylist, 0, {start_frame, end_frame}, false);
1784 }
1785 }
1786 LISTBASE_FOREACH (ActKeyColumn *, column, ED_keylist_listbase(keylist)) {
1787 if (column->cfra <= start_frame) {
1788 continue;
1789 }
1790 if (column->cfra > end_frame) {
1791 break;
1792 }
1793 FrameLink *link = MEM_callocN<FrameLink>("Marker Key Link");
1794 link->frame = column->cfra;
1795 BLI_addtail(target_frames, link);
1796 }
1797 ED_keylist_free(keylist);
1798}
1799
1800static void get_selected_frames(ListBase *pflinks, ListBase /*FrameLink*/ *target_frames)
1801{
1802 AnimKeylist *keylist = ED_keylist_create();
1803 LISTBASE_FOREACH (tPChanFCurveLink *, pfl, pflinks) {
1804 LISTBASE_FOREACH (LinkData *, ld, &pfl->fcurves) {
1805 FCurve *fcu = static_cast<FCurve *>(ld->data);
1806 fcurve_to_keylist(nullptr, fcu, keylist, 0, {-FLT_MAX, FLT_MAX}, false);
1807 }
1808 }
1809 LISTBASE_FOREACH (ActKeyColumn *, column, ED_keylist_listbase(keylist)) {
1810 if (!column->sel) {
1811 continue;
1812 }
1813 FrameLink *link = MEM_callocN<FrameLink>("Marker Key Link");
1814 link->frame = column->cfra;
1815 BLI_addtail(target_frames, link);
1816 }
1817 ED_keylist_free(keylist);
1818}
1819
1820/* --------------------------------- */
1821
1823{
1824 Scene *scene = CTX_data_scene(C);
1825 ViewLayer *view_layer = CTX_data_view_layer(C);
1826 View3D *v3d = CTX_wm_view3d(C);
1827
1828 ListBase pflinks = {nullptr, nullptr};
1829
1830 const int mode = RNA_enum_get(op->ptr, "mode");
1831
1832 /* Isolate F-Curves related to the selected bones. */
1833 poseAnim_mapping_get(C, &pflinks);
1834
1835 if (BLI_listbase_is_empty(&pflinks)) {
1836 /* There is a change the reason the list is empty is
1837 * that there is no valid object to propagate poses for.
1838 * This is very unlikely though, so we focus on the most likely issue. */
1839 BKE_report(op->reports, RPT_ERROR, "No keyframed poses to propagate to");
1840 return OPERATOR_CANCELLED;
1841 }
1842
1843 const float end_frame = RNA_float_get(op->ptr, "end_frame");
1844 const float current_frame = BKE_scene_frame_get(scene);
1845
1846 ListBase target_frames = {nullptr, nullptr};
1847
1848 switch (mode) {
1850 float target_frame = find_next_key(&pflinks, current_frame);
1851 FrameLink *link = MEM_callocN<FrameLink>("Next Key Link");
1852 link->frame = target_frame;
1853 BLI_addtail(&target_frames, link);
1854 propagate_curve_values(&pflinks, current_frame, &target_frames);
1855 break;
1856 }
1857
1859 float target_frame = find_last_key(&pflinks);
1860 FrameLink *link = MEM_callocN<FrameLink>("Last Key Link");
1861 link->frame = target_frame;
1862 BLI_addtail(&target_frames, link);
1863 propagate_curve_values(&pflinks, current_frame, &target_frames);
1864 break;
1865 }
1866
1868 get_selected_marker_positions(scene, &target_frames);
1869 propagate_curve_values(&pflinks, current_frame, &target_frames);
1870 break;
1871 }
1872
1874 get_keyed_frames_in_range(&pflinks, current_frame, FLT_MAX, &target_frames);
1875 propagate_curve_values(&pflinks, current_frame, &target_frames);
1876 break;
1877 }
1879 get_keyed_frames_in_range(&pflinks, current_frame, end_frame, &target_frames);
1880 propagate_curve_values(&pflinks, current_frame, &target_frames);
1881 break;
1882 }
1884 get_selected_frames(&pflinks, &target_frames);
1885 propagate_curve_values(&pflinks, current_frame, &target_frames);
1886 break;
1887 }
1888 }
1889
1890 BLI_freelistN(&target_frames);
1891
1892 /* Free temp data. */
1893 poseAnim_mapping_free(&pflinks);
1894
1895 /* Updates + notifiers. */
1896 FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
1897 poseAnim_mapping_refresh(C, scene, ob);
1898 }
1900
1901 return OPERATOR_FINISHED;
1902}
1903
1904/* --------------------------------- */
1905
1907{
1908 static const EnumPropertyItem terminate_items[] = {
1910 "NEXT_KEY",
1911 0,
1912 "To Next Keyframe",
1913 "Propagate pose to first keyframe following the current frame only"},
1915 "LAST_KEY",
1916 0,
1917 "To Last Keyframe",
1918 "Propagate pose to the last keyframe only (i.e. making action cyclic)"},
1920 "BEFORE_FRAME",
1921 0,
1922 "Before Frame",
1923 "Propagate pose to all keyframes between current frame and 'Frame' property"},
1925 "BEFORE_END",
1926 0,
1927 "Before Last Keyframe",
1928 "Propagate pose to all keyframes from current frame until no more are found"},
1930 "SELECTED_KEYS",
1931 0,
1932 "On Selected Keyframes",
1933 "Propagate pose to all selected keyframes"},
1935 "SELECTED_MARKERS",
1936 0,
1937 "On Selected Markers",
1938 "Propagate pose to all keyframes occurring on frames with Scene Markers after the current "
1939 "frame"},
1940 {0, nullptr, 0, nullptr, nullptr},
1941 };
1942
1943 /* identifiers */
1944 ot->name = "Propagate Pose";
1945 ot->idname = "POSE_OT_propagate";
1946 ot->description =
1947 "Copy selected aspects of the current pose to subsequent poses already keyframed";
1948
1949 /* callbacks */
1950 ot->exec = pose_propagate_exec;
1951 ot->poll = ED_operator_posemode; /* XXX: needs selected bones! */
1952
1953 /* flag */
1954 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1955
1956 /* properties */
1957 /* TODO: add "fade out" control for tapering off amount of propagation as time goes by? */
1958 ot->prop = RNA_def_enum(ot->srna,
1959 "mode",
1960 terminate_items,
1962 "Terminate Mode",
1963 "Method used to determine when to stop propagating pose to keyframes");
1964 RNA_def_float(ot->srna,
1965 "end_frame",
1966 250.0,
1967 FLT_MIN,
1968 FLT_MAX,
1969 "End Frame",
1970 "Frame to stop propagating frames to (for 'Before Frame' mode)",
1971 1.0,
1972 250.0);
1973}
1974
1975/* **************************************************** */
Functions to modify FCurves.
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
int BKE_fcurve_bezt_binarysearch_index(const BezTriple array[], float frame, int arraylen, bool *r_replace)
float evaluate_fcurve(const FCurve *fcu, float evaltime)
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_mode_params(const Scene *scene, ViewLayer *view_layer, const View3D *v3d, const ObjectsInModeParams *params)
#define FOREACH_OBJECT_IN_MODE_END
Definition BKE_layer.hh:382
#define FOREACH_OBJECT_IN_MODE_BEGIN(_scene, _view_layer, _v3d, _object_type, _object_mode, _instance)
Definition BKE_layer.hh:377
@ NLATIME_CONVERT_UNMAP
Definition BKE_nla.hh:540
float BKE_nla_tweakedit_remap(AnimData *adt, float cframe, eNlaTime_ConvertModes mode)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
float BKE_scene_frame_get(const Scene *scene)
Definition scene.cc:2381
@ B_UNIT_NONE
Definition BKE_unit.hh:123
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
MINLINE float interpf(float target, float origin, float t)
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])
void quat_to_compatible_quat(float q[4], const float a[4], const float old[4])
char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
unsigned int uint
#define UNLIKELY(x)
#define ELEM(...)
#define IFACE_(msgid)
@ ROT_MODE_AXISANGLE
@ POSE_SCALE
@ POSE_BBONE_SHAPE
@ POSE_ROT
@ POSE_LOC
@ POSE_LOCKED
@ POSE_DO_UNLOCK
@ INSERTKEY_NOFLAGS
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
@ OB_ARMATURE
#define MINAFRAME
#define MAXFRAME
@ SPACE_VIEW3D
@ V3D_OVERLAY_HIDE_BONES
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void initNumInput(NumInput *n)
Definition numinput.cc:69
#define NUM_STR_REP_LEN
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
Definition numinput.cc:311
bool applyNumInput(NumInput *n, float *vec)
Definition numinput.cc:189
void outputNumInput(NumInput *n, char *str, const UnitSettings &unit_settings)
Definition numinput.cc:87
bool hasNumInput(const NumInput *n)
Definition numinput.cc:170
bool ED_operator_posemode(bContext *C)
void ED_workspace_status_text(bContext *C, const char *str)
Definition area.cc:1040
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:639
void ED_slider_init(tSlider *slider, const wmEvent *event)
Definition ed_draw.cc:483
void ED_slider_property_label_set(tSlider *slider, const char *property_label)
Definition ed_draw.cc:661
void ED_slider_destroy(bContext *C, tSlider *slider)
Definition ed_draw.cc:585
tSlider * ED_slider_create(bContext *C)
Definition ed_draw.cc:434
bool ED_slider_modal(tSlider *slider, const wmEvent *event)
Definition ed_draw.cc:488
void ED_slider_status_get(const tSlider *slider, WorkspaceStatus &status)
Definition ed_draw.cc:569
void ED_slider_factor_bounds_set(tSlider *slider, float factor_bound_lower, float factor_bound_upper)
Definition ed_draw.cc:638
float ED_slider_factor_get(const tSlider *slider)
Definition ed_draw.cc:598
void ED_slider_factor_set(tSlider *slider, float factor)
Definition ed_draw.cc:603
Read Guarded memory(de)allocation.
@ PROP_FLOAT
Definition RNA_types.hh:152
@ PROP_BOOLEAN
Definition RNA_types.hh:150
@ PROP_ENUM
Definition RNA_types.hh:154
@ PROP_INT
Definition RNA_types.hh:151
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
#define C
Definition RandGen.cpp:29
@ KM_PRESS
Definition WM_types.hh:308
@ OPTYPE_BLOCKING
Definition WM_types.hh:184
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
@ OPTYPE_GRAB_CURSOR_X
Definition WM_types.hh:190
void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, const bool only_selected)
void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks, float cframe)
void poseAnim_mapping_free(ListBase *pfLinks)
void poseAnim_mapping_reset(ListBase *pfLinks)
void poseAnim_mapping_get(bContext *C, ListBase *pfLinks)
Object * poseAnim_object_get(Object *ob_)
void poseAnim_mapping_refresh(bContext *C, Scene *scene, Object *ob)
LinkData * poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, const char *path)
volatile int lock
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:398
void item_bool(std::string text, bool inverted, int icon1, int icon2=0)
Definition area.cc:995
void item(std::string text, int icon1, int icon2=0)
Definition area.cc:979
int64_t size() const
IndexRange index_range() const
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
const ActKeyColumn * ED_keylist_find_prev(const AnimKeylist *keylist, const float cfra)
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, const int saction_flag, blender::float2 range, const bool use_nla_remapping)
void ED_keylist_prepare_for_direct_access(AnimKeylist *keylist)
AnimKeylist * ED_keylist_create()
void ED_keylist_free(AnimKeylist *keylist)
const ActKeyColumn * ED_keylist_find_next(const AnimKeylist *keylist, const float cfra)
const ListBase * ED_keylist_listbase(const AnimKeylist *keylist)
bool ED_keylist_is_empty(const AnimKeylist *keylist)
const ActKeyColumn * ED_keylist_find_exact(const AnimKeylist *keylist, const float cfra)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float2 fabs(const float2 a)
KeyframeSettings get_keyframe_settings(bool from_userprefs)
SingleKeyingResult insert_vert_fcurve(FCurve *fcu, const float2 position, const KeyframeSettings &settings, eInsertKeyFlags flag)
Main Key-framing API call.
ePoseSlide_Modes
Definition pose_slide.cc:86
@ POSESLIDE_BLEND
Definition pose_slide.cc:94
@ POSESLIDE_BREAKDOWN
Definition pose_slide.cc:92
@ POSESLIDE_PUSH
Definition pose_slide.cc:88
@ POSESLIDE_BLEND_REST
Definition pose_slide.cc:93
@ POSESLIDE_RELAX
Definition pose_slide.cc:90
static void pose_slide_toggle_channels_mode(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_Channels channel)
static wmOperatorStatus pose_slide_blend_rest_exec(bContext *C, wmOperator *op)
static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
void POSE_OT_breakdown(wmOperatorType *ot)
static wmOperatorStatus pose_slide_push_exec(bContext *C, wmOperator *op)
static wmOperatorStatus pose_slide_blend_to_neighbors_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static const EnumPropertyItem prop_channels_types[]
static wmOperatorStatus pose_slide_blend_to_neighbors_exec(bContext *C, wmOperator *op)
static void pose_slide_apply_val(tPoseSlideOp *pso, const FCurve *fcu, Object *ob, float *val)
static void pose_slide_reset(tPoseSlideOp *pso)
static void pose_slide_cancel(bContext *C, wmOperator *op)
static wmOperatorStatus pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus pose_slide_relax_exec(bContext *C, wmOperator *op)
static void get_keyed_frames_in_range(ListBase *pflinks, const float start_frame, const float end_frame, ListBase *target_frames)
ePoseSlide_AxisLock
Definition pose_slide.cc:79
@ PS_LOCK_Z
Definition pose_slide.cc:82
@ PS_LOCK_Y
Definition pose_slide.cc:81
@ PS_LOCK_X
Definition pose_slide.cc:80
static const EnumPropertyItem prop_axis_lock_types[]
static bool pose_slide_toggle_axis_locks(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_AxisLock axis)
static wmOperatorStatus pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void pose_slide_rest_pose_apply_other_rot(tPoseSlideOp *pso, float vec[4], bool quat)
static void pose_slide_opdef_properties(wmOperatorType *ot)
static void pose_slide_refresh(bContext *C, tPoseSlideOp *pso)
static float find_next_key(ListBase *pflinks, const float start_frame)
static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
void POSE_OT_blend_with_rest(wmOperatorType *ot)
static wmOperatorStatus pose_slide_invoke_common(bContext *C, wmOperator *op, const wmEvent *event)
void POSE_OT_propagate(wmOperatorType *ot)
static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso)
static wmOperatorStatus pose_slide_breakdown_exec(bContext *C, wmOperator *op)
static void pose_slide_autoKeyframe(bContext *C, tPoseSlideOp *pso)
static float find_last_key(ListBase *pflinks)
static wmOperatorStatus pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void propagate_curve_values(ListBase *pflinks, const float source_frame, ListBase *target_frames)
static wmOperatorStatus pose_propagate_exec(bContext *C, wmOperator *op)
static bool pose_frame_range_from_object_get(tPoseSlideOp *pso, Object *ob, float *prev_frame, float *next_frame)
void POSE_OT_relax(wmOperatorType *ot)
static void pose_slide_apply_vec3(tPoseSlideOp *pso, tPChanFCurveLink *pfl, float vec[3], const char propName[])
static wmOperatorStatus pose_slide_blend_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ePoseSlide_Channels
Definition pose_slide.cc:98
@ PS_TFM_LOC
@ PS_TFM_PROPS
@ PS_TFM_ALL
Definition pose_slide.cc:99
@ PS_TFM_SCALE
@ PS_TFM_BBONE_SHAPE
@ PS_TFM_ROT
static wmOperatorStatus pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
void POSE_OT_push(wmOperatorType *ot)
static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode)
static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], float default_value)
static void get_selected_frames(ListBase *pflinks, ListBase *target_frames)
static void pose_slide_draw_status(bContext *C, tPoseSlideOp *pso)
ePosePropagate_Termination
@ POSE_PROPAGATE_LAST_KEY
@ POSE_PROPAGATE_BEFORE_FRAME
@ POSE_PROPAGATE_SELECTED_MARKERS
@ POSE_PROPAGATE_BEFORE_END
@ POSE_PROPAGATE_NEXT_KEY
@ POSE_PROPAGATE_SELECTED_KEYS
static void get_selected_marker_positions(Scene *scene, ListBase *target_frames)
static void pose_slide_apply_props(tPoseSlideOp *pso, tPChanFCurveLink *pfl, const char prop_prefix[])
static void pose_slide_exit(bContext *C, wmOperator *op)
static wmOperatorStatus pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso)
void POSE_OT_blend_to_neighbors(wmOperatorType *ot)
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, bool value)
void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
bool RNA_property_array_check(PropertyRNA *prop)
int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
PropertyType RNA_property_type(PropertyRNA *prop)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_int_get(PointerRNA *ptr, const char *name)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float_factor(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
#define FLT_MAX
Definition stdcycles.h:14
ActKeyColumn * prev
ActKeyColumn * next
float vec[3][3]
char * rna_path
BezTriple * bezt
int array_index
unsigned int totvert
void * data
void * first
short idx_max
int unit_type[NUM_MAX_ELEMENTS]
struct bPose * pose
struct AnimData * adt
struct RenderData r
struct UnitSettings unit
ListBase markers
ListBase spacedata
View3DOverlay overlay
ePoseSlide_Channels channels
NumInput num
ePoseSlide_AxisLock axislock
ARegion * region
tSlider * slider
ScrArea * area
AnimKeylist * keylist
ePoseSlide_Modes mode
ListBase pfLinks
Scene * scene
blender::Array< tPoseSlideObject > ob_data_array
wmEventType type
Definition WM_types.hh:754
short val
Definition WM_types.hh:756
struct ReportList * reports
struct PointerRNA * ptr
uint len
void WM_cursor_modal_set(wmWindow *win, int val)
void WM_cursor_modal_restore(wmWindow *win)
@ WM_CURSOR_EW_SCROLL
Definition wm_cursors.hh:54
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.cc:4227
wmOperatorType * ot
Definition wm_files.cc:4226