[Bf-blender-cvs] [f7a492d4605] master: Animation: Pose Slide Operator - Blend to Neighbour

Christoph Lendenfeld noreply at git.blender.org
Wed Sep 22 15:02:25 CEST 2021


Commit: f7a492d460543fd42386cb0c941d247ea902f290
Author: Christoph Lendenfeld
Date:   Wed Sep 22 14:02:19 2021 +0100
Branches: master
https://developer.blender.org/rBf7a492d460543fd42386cb0c941d247ea902f290

Animation: Pose Slide Operator - Blend to Neighbour

Adds a new operator to the pose slider tools that blends the
current pose with the neighbouring poses in the timeline.
The operator can be called in pose mode with Shift+Alt+E
or from the "pose" menu under "In betweens/Blend to Neighbour"

Reviewed by: Sybren A. Stüvel
Differential Revision: https://developer.blender.org/D9137#inline-105214
Ref: D9137

===================================================================

M	release/scripts/presets/keyconfig/keymap_data/blender_default.py
M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/editors/armature/armature_intern.h
M	source/blender/editors/armature/armature_ops.c
M	source/blender/editors/armature/pose_slide.c

===================================================================

diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 15d6d44d240..1b0da23aa4a 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -4265,6 +4265,7 @@ def km_pose(params):
         ("pose.push", {"type": 'E', "value": 'PRESS', "ctrl": True}, None),
         ("pose.relax", {"type": 'E', "value": 'PRESS', "alt": True}, None),
         ("pose.breakdown", {"type": 'E', "value": 'PRESS', "shift": True}, None),
+        ("pose.blend_to_neighbour", {"type": 'E', "value": 'PRESS', "shift": True, "alt": True}, None),
         op_menu("VIEW3D_MT_pose_propagate", {"type": 'P', "value": 'PRESS', "alt": True}),
         *(
             (("object.hide_collection",
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index a332295715c..3879f7de250 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -3453,6 +3453,7 @@ class VIEW3D_MT_pose_slide(Menu):
         layout.operator("pose.push")
         layout.operator("pose.relax")
         layout.operator("pose.breakdown")
+        layout.operator("pose.blend_to_neighbour")
 
 
 class VIEW3D_MT_pose_propagate(Menu):
@@ -3605,6 +3606,7 @@ class VIEW3D_MT_pose_context_menu(Menu):
         layout.operator("pose.push")
         layout.operator("pose.relax")
         layout.operator("pose.breakdown")
+        layout.operator("pose.blend_to_neighbour")
 
         layout.separator()
 
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index f9950d27e97..696355324e6 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -216,6 +216,7 @@ void POSE_OT_relax(struct wmOperatorType *ot);
 void POSE_OT_push_rest(struct wmOperatorType *ot);
 void POSE_OT_relax_rest(struct wmOperatorType *ot);
 void POSE_OT_breakdown(struct wmOperatorType *ot);
+void POSE_OT_blend_to_neighbours(struct wmOperatorType *ot);
 
 void POSE_OT_propagate(struct wmOperatorType *ot);
 
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index fbd89106de5..a1070a8823a 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -150,6 +150,7 @@ void ED_operatortypes_armature(void)
   WM_operatortype_append(POSE_OT_push_rest);
   WM_operatortype_append(POSE_OT_relax_rest);
   WM_operatortype_append(POSE_OT_breakdown);
+  WM_operatortype_append(POSE_OT_blend_to_neighbours);
 }
 
 void ED_operatormacros_armature(void)
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index f23376867af..b273d3aac76 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -117,6 +117,7 @@ typedef enum ePoseSlide_Modes {
   POSESLIDE_BREAKDOWN,
   POSESLIDE_PUSH_REST,
   POSESLIDE_RELAX_REST,
+  POSESLIDE_BLEND,
 } ePoseSlide_Modes;
 
 /** Transforms/Channels to Affect. */
@@ -423,6 +424,25 @@ static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, flo
       (*val) = ((sVal * w2) + (eVal * w1));
       break;
     }
+    case POSESLIDE_BLEND: /* Blend the current pose with the previous (<50%) or next key (>50%). */
+    {
+      /* FCurve value on current frame. */
+      const float cVal = evaluate_fcurve(fcu, cframe);
+      const float factor = ED_slider_factor_get(pso->slider);
+      /* Convert factor to absolute 0-1 range. */
+      const float blend_factor = fabs((factor - 0.5f) * 2);
+
+      if (factor < 0.5) {
+        /* Blend to previous key. */
+        (*val) = (cVal * (1 - blend_factor)) + (sVal * blend_factor);
+      }
+      else {
+        /* Blend to next key. */
+        (*val) = (cVal * (1 - blend_factor)) + (eVal * blend_factor);
+      }
+
+      break;
+    }
     /* Those are handled in pose_slide_rest_pose_apply. */
     case POSESLIDE_PUSH_REST:
     case POSESLIDE_RELAX_REST: {
@@ -614,8 +634,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
 
       interp_qt_qtqt(quat_final, quat_prev, quat_next, ED_slider_factor_get(pso->slider));
     }
-    else {
-      /* POSESLIDE_PUSH and POSESLIDE_RELAX. */
+    else if (pso->mode == POSESLIDE_PUSH || pso->mode == POSESLIDE_RELAX) {
       float quat_breakdown[4];
       float quat_curr[4];
 
@@ -638,6 +657,32 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
         interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, ED_slider_factor_get(pso->slider));
       }
     }
+    else if (pso->mode == POSESLIDE_BLEND) {
+      float quat_blend[4];
+      float quat_curr[4];
+
+      copy_qt_qt(quat_curr, pchan->quat);
+
+      if (ED_slider_factor_get(pso->slider) < 0.5) {
+        quat_blend[0] = evaluate_fcurve(fcu_w, prevFrameF);
+        quat_blend[1] = evaluate_fcurve(fcu_x, prevFrameF);
+        quat_blend[2] = evaluate_fcurve(fcu_y, prevFrameF);
+        quat_blend[3] = evaluate_fcurve(fcu_z, prevFrameF);
+      }
+      else {
+        quat_blend[0] = evaluate_fcurve(fcu_w, nextFrameF);
+        quat_blend[1] = evaluate_fcurve(fcu_x, nextFrameF);
+        quat_blend[2] = evaluate_fcurve(fcu_y, nextFrameF);
+        quat_blend[3] = evaluate_fcurve(fcu_z, nextFrameF);
+      }
+
+      normalize_qt(quat_blend);
+      normalize_qt(quat_curr);
+
+      const float blend_factor = fabs((ED_slider_factor_get(pso->slider) - 0.5f) * 2);
+
+      interp_qt_qtqt(quat_final, quat_curr, quat_blend, blend_factor);
+    }
 
     /* Apply final to the pose bone, keeping compatible for similar keyframe positions. */
     quat_to_compatible_quat(pchan->quat, quat_final, pchan->quat);
@@ -868,6 +913,9 @@ static void pose_slide_draw_status(bContext *C, tPoseSlideOp *pso)
     case POSESLIDE_BREAKDOWN:
       strcpy(mode_str, TIP_("Breakdown"));
       break;
+    case POSESLIDE_BLEND:
+      strcpy(mode_str, TIP_("Blend To Neighbour"));
+      break;
 
     default:
       /* Unknown. */
@@ -1660,6 +1708,56 @@ void POSE_OT_breakdown(wmOperatorType *ot)
   pose_slide_opdef_properties(ot);
 }
 
+/* ........................ */
+static int pose_slide_blend_to_neighbours_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+  /* Initialize data. */
+  if (pose_slide_init(C, op, POSESLIDE_BLEND) == 0) {
+    pose_slide_exit(C, op);
+    return OPERATOR_CANCELLED;
+  }
+
+  /* Do common setup work. */
+  return pose_slide_invoke_common(C, op, event);
+}
+
+static int pose_slide_blend_to_neighbours_exec(bContext *C, wmOperator *op)
+{
+  tPoseSlideOp *pso;
+
+  /* Initialize data (from RNA-props). */
+  if (pose_slide_init(C, op, POSESLIDE_BLEND) == 0) {
+    pose_slide_exit(C, op);
+    return OPERATOR_CANCELLED;
+  }
+
+  pso = op->customdata;
+
+  /* Do common exec work. */
+  return pose_slide_exec_common(C, op, pso);
+}
+
+void POSE_OT_blend_to_neighbours(wmOperatorType *ot)
+{
+  /* Identifiers. */
+  ot->name = "Blend To Neighbour";
+  ot->idname = "POSE_OT_blend_to_neighbour";
+  ot->description = "Blend from current position to previous or next keyframe";
+
+  /* Callbacks. */
+  ot->exec = pose_slide_blend_to_neighbours_exec;
+  ot->invoke = pose_slide_blend_to_neighbours_invoke;
+  ot->modal = pose_slide_modal;
+  ot->cancel = pose_slide_cancel;
+  ot->poll = ED_operator_posemode;
+
+  /* Flags. */
+  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_X;
+
+  /* Properties. */
+  pose_slide_opdef_properties(ot);
+}
+
 /* **************************************************** */
 /* B) Pose Propagate */



More information about the Bf-blender-cvs mailing list