diff options
-rw-r--r-- | release/scripts/startup/bl_ui/space_view3d.py | 7 | ||||
-rw-r--r-- | source/blender/editors/armature/poseSlide.c | 54 | ||||
-rw-r--r-- | source/blender/editors/armature/poseUtils.c | 12 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_select.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_select.c | 2 |
5 files changed, 68 insertions, 9 deletions
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index f026a26c984..13270a8c6fd 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -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" diff --git a/source/blender/editors/armature/poseSlide.c b/source/blender/editors/armature/poseSlide.c index 31fcf0a1253..203d76086b3 100644 --- a/source/blender/editors/armature/poseSlide.c +++ b/source/blender/editors/armature/poseSlide.c @@ -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 */ diff --git a/source/blender/editors/armature/poseUtils.c b/source/blender/editors/armature/poseUtils.c index 16e84db0ba7..7ade93076e5 100644 --- a/source/blender/editors/armature/poseUtils.c +++ b/source/blender/editors/armature/poseUtils.c @@ -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 */ diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index f9687e99c87..bee872dbe60 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -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 */ diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 8bec0803c5e..920f477e7eb 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -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 */ |