Pose Propagate - Further Tweaks:
authorJoshua Leung <aligorith@gmail.com>
Thu, 31 Mar 2011 01:37:42 +0000 (01:37 +0000)
committerJoshua Leung <aligorith@gmail.com>
Thu, 31 Mar 2011 01:37:42 +0000 (01:37 +0000)
- Pose Propagate and Pose Sliding tools now work in the same way as
Pose Library previewing, with regards to selections. If some bones are
selected, then only those will be affected. But if no bones are
selected, then the whole rig gets affected.
- Added a "On Selected Markers" option, which only propagates poses to
frames where there's a selected marker. Animators can combine this
with a "select markers whose name contains..." operator to get an
effective way to manage hand-keyed walk cycles, etc.

release/scripts/startup/bl_ui/space_view3d.py
source/blender/editors/armature/poseSlide.c
source/blender/editors/armature/poseUtils.c
source/blender/editors/space_action/action_select.c
source/blender/editors/space_graph/graph_select.c

index f026a26c9845d73abaa209a9672158207cb32e6a..13270a8c6fdcfabc515c0ffc8cddda8229afe1ae 100644 (file)
@@ -1258,9 +1258,16 @@ class VIEW3D_MT_pose_propagate(bpy.types.Menu):
         layout = self.layout
 
         layout.operator("pose.propagate")
+
+        layout.separator()
+
         layout.operator("pose.propagate", text="To Next Keyframe").mode = 'NEXT_KEY'
         layout.operator("pose.propagate", text="To Last Keyframe (Make Cyclic)").mode = 'LAST_KEY'
 
+        layout.separator()
+
+        layout.operator("pose.propagate", text="On Selected Markers").mode = 'SELECTED_MARKERS'
+
 
 class VIEW3D_MT_pose_library(bpy.types.Menu):
     bl_label = "Pose Library"
index 31fcf0a125371ca2ce8284873f9213a69649d1f4..203d76086b32568f31db9161ce6f00b1bdad8116 100644 (file)
@@ -63,6 +63,7 @@
 
 #include "ED_armature.h"
 #include "ED_keyframes_draw.h"
+#include "ED_markers.h"
 #include "ED_screen.h"
 
 #include "armature_intern.h"
@@ -871,9 +872,21 @@ typedef enum ePosePropagate_Termination {
                /* stop after the specified frame */
        POSE_PROPAGATE_BEFORE_FRAME,
                /* stop when we run out of keyframes */
-       POSE_PROPAGATE_BEFORE_END
+       POSE_PROPAGATE_BEFORE_END,
+       
+               /* only do on the frames where markers are selected */
+       POSE_PROPAGATE_SELECTED_MARKERS
 } ePosePropagate_Termination;
 
+/* termination data needed for some modes - assumes only one of these entries will be needed at a time */
+typedef union tPosePropagate_ModeData {
+       /* smart holds + before frame: frame number to stop on */
+       float end_frame;
+       
+       /* selected markers: listbase for CfraElem's marking these frames */
+       ListBase sel_markers;
+} tPosePropagate_ModeData;
+
 /* --------------------------------- */
 
 /* get frame on which the "hold" for the bone ends 
@@ -1030,7 +1043,8 @@ static float pose_propagate_get_refVal (Object *ob, FCurve *fcu)
 }
 
 /* propagate just works along each F-Curve in turn */
-static void pose_propagate_fcurve (wmOperator *op, Object *ob, tPChanFCurveLink *UNUSED(pfl), FCurve *fcu, float startFrame, float endFrame)
+static void pose_propagate_fcurve (wmOperator *op, Object *ob, FCurve *fcu, 
+                               float startFrame, tPosePropagate_ModeData modeData)
 {
        const int mode = RNA_enum_get(op->ptr, "mode");
        
@@ -1067,7 +1081,7 @@ static void pose_propagate_fcurve (wmOperator *op, Object *ob, tPChanFCurveLink
                /* additional termination conditions based on the operator 'mode' property go here... */
                if (ELEM(mode, POSE_PROPAGATE_BEFORE_FRAME, POSE_PROPAGATE_SMART_HOLDS)) {
                        /* stop if keyframe is outside the accepted range */
-                       if (bezt->vec[1][0] > endFrame)
+                       if (bezt->vec[1][0] > modeData.end_frame)
                                break; 
                }
                else if (mode == POSE_PROPAGATE_NEXT_KEY) {
@@ -1080,6 +1094,20 @@ static void pose_propagate_fcurve (wmOperator *op, Object *ob, tPChanFCurveLink
                        if (i != (fcu->totvert-1))
                                continue;
                }
+               else if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
+                       /* only allow if there's a marker on this frame */
+                       CfraElem *ce = NULL;
+                       
+                       /* stop on matching marker if there is one */
+                       for (ce = modeData.sel_markers.first; ce; ce = ce->next) {
+                               if (ce->cfra == (int)(floor(bezt->vec[1][0] + 0.5f)))
+                                       break;
+                       }
+                       
+                       /* skip this keyframe if no marker */
+                       if (ce == NULL)
+                               continue;
+               }
                
                /* just flatten handles, since values will now be the same either side... */
                // TODO: perhaps a fade-out modulation of the value is required here (optional once again)?
@@ -1102,7 +1130,7 @@ static int pose_propagate_exec (bContext *C, wmOperator *op)
        ListBase pflinks = {NULL, NULL};
        tPChanFCurveLink *pfl;
        
-       float endFrame = RNA_float_get(op->ptr, "end_frame");
+       tPosePropagate_ModeData modeData;
        const int mode = RNA_enum_get(op->ptr, "mode");
        
        /* sanity checks */
@@ -1118,6 +1146,16 @@ static int pose_propagate_exec (bContext *C, wmOperator *op)
        /* isolate F-Curves related to the selected bones */
        poseAnim_mapping_get(C, &pflinks, ob, act);
        
+       /* mode-specific data preprocessing (requiring no access to curves) */
+       if (mode == POSE_PROPAGATE_SELECTED_MARKERS) {
+               /* get a list of selected markers */
+               ED_markers_make_cfra_list(&scene->markers, &modeData.sel_markers, SELECT);
+       }
+       else {
+               /* assume everything else wants endFrame */
+               modeData.end_frame = RNA_float_get(op->ptr, "end_frame");
+       }
+       
        /* for each bone, perform the copying required */
        for (pfl = pflinks.first; pfl; pfl = pfl->next) {
                LinkData *ld;
@@ -1127,17 +1165,20 @@ static int pose_propagate_exec (bContext *C, wmOperator *op)
                        /* we store in endFrame the end frame of the "long keyframe" (i.e. a held value) starting
                         * from the keyframe that occurs after the current frame
                         */
-                       endFrame = pose_propagate_get_boneHoldEndFrame(ob, pfl, (float)CFRA);
+                       modeData.end_frame = pose_propagate_get_boneHoldEndFrame(ob, pfl, (float)CFRA);
                }
                
                /* go through propagating pose to keyframes, curve by curve */
                for (ld = pfl->fcurves.first; ld; ld= ld->next)
-                       pose_propagate_fcurve(op, ob, pfl, (FCurve *)ld->data, (float)CFRA, endFrame);
+                       pose_propagate_fcurve(op, ob, (FCurve *)ld->data, (float)CFRA, modeData);
        }
        
        /* free temp data */
        poseAnim_mapping_free(&pflinks);
        
+       if (mode == POSE_PROPAGATE_SELECTED_MARKERS)
+               BLI_freelistN(&modeData.sel_markers);
+       
        /* updates + notifiers */
        poseAnim_mapping_refresh(C, scene, ob);
        
@@ -1154,6 +1195,7 @@ void POSE_OT_propagate (wmOperatorType *ot)
                {POSE_PROPAGATE_LAST_KEY, "LAST_KEY", 0, "To Last Keyframe", "Propagate pose to the last keyframe only (i.e. making action cyclic)"},
                {POSE_PROPAGATE_BEFORE_FRAME, "BEFORE_FRAME", 0, "Before Frame", "Propagate pose to all keyframes between current frame and 'Frame' property"},
                {POSE_PROPAGATE_BEFORE_END, "BEFORE_END", 0, "Before Last Keyframe", "Propagate pose to all keyframes from current frame until no more are found"},
+               {POSE_PROPAGATE_SELECTED_MARKERS, "SELECTED_MARKERS", 0, "On Selected Markers", "Propagate pose to all keyframes occurring on frames with Scene Markers after the current frame"},
                {0, NULL, 0, NULL, NULL}};
                
        /* identifiers */
index 16e84db0ba79a1cfd6ab5d5616f6d23c0c76f922..7ade93076e5a44f8e07f5db87104f9ea8534fe5b 100644 (file)
@@ -128,7 +128,6 @@ static void fcurves_to_pchan_links_get (ListBase *pfLinks, Object *ob, bAction *
 
 
 /* get sets of F-Curves providing transforms for the bones in the Pose  */
-// TODO: separate the inner workings out to another helper func, since we need option of whether to take selected or visible bones...
 void poseAnim_mapping_get (bContext *C, ListBase *pfLinks, Object *ob, bAction *act)
 {      
        /* for each Pose-Channel which gets affected, get the F-Curves for that channel 
@@ -139,6 +138,17 @@ void poseAnim_mapping_get (bContext *C, ListBase *pfLinks, Object *ob, bAction *
                fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
        }
        CTX_DATA_END;
+       
+       /* if no PoseChannels were found, try a second pass, doing visible ones instead
+        * i.e. if nothing selected, do whole pose
+        */
+       if (pfLinks->first == NULL) {
+               CTX_DATA_BEGIN(C, bPoseChannel*, pchan, visible_pose_bones)
+               {
+                       fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
+               }
+               CTX_DATA_END;
+       }
 }
 
 /* free F-Curve <-> PoseChannel links  */
index f9687e99c874de1ad67708fdea3a006088bf95de..bee872dbe607b0179e29061403eb8049e5cbc3b6 100644 (file)
@@ -455,7 +455,7 @@ static void columnselect_action_keys (bAnimContext *ac, short mode)
                        break;
                        
                case ACTKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
-                       ED_markers_make_cfra_list(ac->markers, &ked.list, 1);
+                       ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT);
                        break;
                        
                default: /* invalid option */
index 8bec0803c5e23a4af6737c765b70e7049dcd7bdc..920f477e7ebe3424ca214654422400de80b7498b 100644 (file)
@@ -459,7 +459,7 @@ static void columnselect_graph_keys (bAnimContext *ac, short mode)
                        break;
                        
                case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
-                       ED_markers_make_cfra_list(ac->markers, &ked.list, 1);
+                       ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT);
                        break;
                        
                default: /* invalid option */