diff options
author | Antony Riakiotakis <kalast@gmail.com> | 2015-05-13 21:30:53 +0300 |
---|---|---|
committer | Antony Riakiotakis <kalast@gmail.com> | 2015-05-15 14:39:30 +0300 |
commit | e4c93dc7db9b50acf898b667c95b208856b80ea8 (patch) | |
tree | c3db350ee276b7437d8ed69133fe51d21750e9ae | |
parent | c86a6f3efbffbf81b663eb1fb57b4736d8e906ee (diff) |
Zoom to frame options, requested by the Hwoozeberry (dutch translation)
team.
There are 3 options here:
1) Keep range (previous behaviour)
2) Seconds - allows a specified offset in seconds around current frame
3) keyframes - zoom to include a number of keyframes around the cursor
Options 2 and 3 have their own properties to tweak the behaviour and all
options can be found in User Preferences->Interface under the 2D
viewports section.
Number 3 will probably need some refinement so commiting here for the
hwoozeberry team to test first.
-rw-r--r-- | release/scripts/startup/bl_ui/space_userpref.py | 5 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_draw.c | 140 | ||||
-rw-r--r-- | source/blender/editors/include/ED_anim_api.h | 1 | ||||
-rw-r--r-- | source/blender/editors/include/UI_view2d.h | 1 | ||||
-rw-r--r-- | source/blender/editors/interface/view2d_ops.c | 15 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_edit.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_edit.c | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_userdef_types.h | 12 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_userdef.c | 27 |
9 files changed, 184 insertions, 21 deletions
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 3b17e40c294..9b3a2b50121 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -200,6 +200,11 @@ class USERPREF_PT_interface(Panel): col.label(text="2D Viewports:") col.prop(view, "view2d_grid_spacing_min", text="Minimum Grid Spacing") col.prop(view, "timecode_style") + col.prop(view, "view_frame_type") + if (view.view_frame_type == 'SECONDS'): + col.prop(view, "view_frame_seconds") + elif (view.view_frame_type == 'KEYFRAMES'): + col.prop(view, "view_frame_keyframes") row.separator() row.separator() diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 54d371d8f50..7d669e8c93e 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -34,17 +34,25 @@ #include "DNA_scene_types.h" #include "DNA_space_types.h" #include "DNA_userdef_types.h" +#include "DNA_screen_types.h" +#include "DNA_object_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_mask_types.h" #include "BLI_math.h" #include "BLI_timecode.h" #include "BLI_utildefines.h" +#include "BLI_rect.h" +#include "BLI_dlrbTree.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_nla.h" +#include "BKE_mask.h" #include "ED_anim_api.h" #include "ED_keyframes_edit.h" +#include "ED_keyframes_draw.h" #include "RNA_access.h" @@ -381,4 +389,136 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag return 1.0f; } +static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prevfra) { + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + bGPdata *gpd = CTX_data_gpencil_data(C); + Mask *mask = CTX_data_edit_mask(C); + bDopeSheet ads = {NULL}; + DLRBT_Tree keys; + ActKeyColumn *aknext, *akprev; + float cfranext, cfraprev; + bool donenext = false, doneprev = false; + int nextcount = 0, prevcount = 0; + + cfranext = cfraprev = (float)(CFRA); + + /* init binarytree-list for getting keyframes */ + BLI_dlrbTree_init(&keys); + + /* seed up dummy dopesheet context with flags to perform necessary filtering */ + if ((scene->flag & SCE_KEYS_NO_SELONLY) == 0) { + /* only selected channels are included */ + ads.filterflag |= ADS_FILTER_ONLYSEL; + } + + /* populate tree with keyframe nodes */ + scene_to_keylist(&ads, scene, &keys, NULL); + + if (ob) + ob_to_keylist(&ads, ob, &keys, NULL); + + gpencil_to_keylist(&ads, gpd, &keys); + + if (mask) { + MaskLayer *masklay = BKE_mask_layer_active(mask); + mask_to_keylist(&ads, masklay, &keys); + } + + /* build linked-list for searching */ + BLI_dlrbTree_linkedlist_sync(&keys); + + /* find matching keyframe in the right direction */ + do { + aknext = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfranext); + + if (aknext) { + if (CFRA == (int)aknext->cfra) { + /* make this the new starting point for the search and ignore */ + cfranext = aknext->cfra; + } + else { + /* this changes the frame, so set the frame and we're done */ + if (++nextcount == U.view_frame_keyframes) + donenext = true; + } + cfranext = aknext->cfra; + } + } while ((aknext != NULL) && (donenext == false)); + + do { + akprev = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfraprev); + + if (akprev) { + if (CFRA == (int)akprev->cfra) { + /* make this the new starting point for the search */ + } + else { + /* this changes the frame, so set the frame and we're done */ + if (++prevcount == U.view_frame_keyframes) + doneprev = true; + } + cfraprev = akprev->cfra; + } + } while ((akprev != NULL) && (doneprev == false)); + + /* free temp stuff */ + BLI_dlrbTree_free(&keys); + + /* any success? */ + if (doneprev || donenext) { + if (doneprev) + *prevfra = cfraprev; + else + *prevfra = CFRA - (cfranext - CFRA); + + if (donenext) + *nextfra = cfranext; + else + *nextfra = CFRA + (CFRA - cfraprev); + + return true; + } + + return false; +} + +void ANIM_center_frame(struct bContext *C, int smooth_viewtx) +{ + ARegion *ar = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); + float w = BLI_rctf_size_x(&ar->v2d.cur); + rctf newrct; + int nextfra, prevfra; + + switch (U.view_frame_type) { + case ZOOM_FRAME_MODE_SECONDS: + newrct.xmax = scene->r.cfra + U.view_frame_seconds * FPS + 1; + newrct.xmin = scene->r.cfra - U.view_frame_seconds * FPS - 1; + newrct.ymax = ar->v2d.cur.ymax; + newrct.ymin = ar->v2d.cur.ymin; + break; + + /* hardest case of all, look for all keyframes around frame and display those */ + case ZOOM_FRAME_MODE_KEYFRAMES: + if (find_prev_next_keyframes(C, &nextfra, &prevfra)) { + newrct.xmax = nextfra; + newrct.xmin = prevfra; + newrct.ymax = ar->v2d.cur.ymax; + newrct.ymin = ar->v2d.cur.ymin; + break; + } + /* else drop through, keep range instead */ + + case ZOOM_FRAME_MODE_KEEP_RANGE: + default: + newrct.xmax = scene->r.cfra + (w / 2); + newrct.xmin = scene->r.cfra - (w / 2); + newrct.ymax = ar->v2d.cur.ymax; + newrct.ymin = ar->v2d.cur.ymin; + break; + } + + UI_view2d_smooth_view(C, ar, &newrct, smooth_viewtx); +} /* *************************************************** */ diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 73f28986375..0f70bf3c745 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -659,6 +659,7 @@ void ANIM_list_elem_update(struct Scene *scene, bAnimListElem *ale); /* data -> channels syncing */ void ANIM_sync_animchannels_to_data(const struct bContext *C); +void ANIM_center_frame(struct bContext *C, int smooth_viewtx); /* ************************************************* */ /* OPERATORS */ diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 430093b641b..2c8f5f6590a 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -233,7 +233,6 @@ void ED_keymap_view2d(struct wmKeyConfig *keyconf); void UI_view2d_smooth_view(struct bContext *C, struct ARegion *ar, const struct rctf *cur, const int smooth_viewtx); -void UI_view2d_center_frame(struct bContext *C, int smooth_viewtx); #define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC) #endif /* __UI_VIEW2D_H__ */ diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 9fed02ee096..eafc5c1d24c 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1468,21 +1468,6 @@ void UI_view2d_smooth_view( } } -void UI_view2d_center_frame(struct bContext *C, int smooth_viewtx) -{ - ARegion *ar = CTX_wm_region(C); - Scene *scene = CTX_data_scene(C); - float w = BLI_rctf_size_x(&ar->v2d.cur); - rctf newrct; - - newrct.xmax = scene->r.cfra + (w / 2); - newrct.xmin = scene->r.cfra - (w / 2); - newrct.ymax = ar->v2d.cur.ymax; - newrct.ymin = ar->v2d.cur.ymin; - - UI_view2d_smooth_view(C, ar, &newrct, smooth_viewtx); -} - /* only meant for timer usage */ static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index debe3cb9730..90c38426164 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -429,7 +429,7 @@ static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op)) static int actkeys_view_frame_exec(bContext *C, wmOperator *op) { const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - UI_view2d_center_frame(C, smooth_viewtx); + ANIM_center_frame(C, smooth_viewtx); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index d450335d16a..a8cb4ce56ea 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -261,7 +261,7 @@ static int graphkeys_view_selected_exec(bContext *C, wmOperator *op) static int graphkeys_view_frame_exec(bContext *C, wmOperator *op) { const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - UI_view2d_center_frame(C, smooth_viewtx); + ANIM_center_frame(C, smooth_viewtx); return OPERATOR_FINISHED; } diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index e0b51a1b25b..af0c3bfbf0e 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -503,7 +503,10 @@ typedef struct UserDef { char ipo_new; /* interpolation mode for newly added F-Curves */ char keyhandles_new; /* handle types for newly added keyframes */ char gpu_select_method; - char pad1; + char view_frame_type; + + int view_frame_keyframes; /* number of keyframes to zoom around current frame */ + float view_frame_seconds; /* seconds to zoom around current frame */ short scrcastfps; /* frame rate for screencast to be played back */ short scrcastwait; /* milliseconds between screencast snapshots */ @@ -686,6 +689,13 @@ typedef enum eAutokey_Mode { AUTOKEY_MODE_EDITKEYS = 5 } eAutokey_Mode; +/* Zoom to frame mode */ +typedef enum eZoomFrame_Mode { + ZOOM_FRAME_MODE_KEEP_RANGE = 0, + ZOOM_FRAME_MODE_SECONDS = 1, + ZOOM_FRAME_MODE_KEYFRAMES = 2 +} eZoomFrame_Mode; + /* Auto-Keying flag * U.autokey_flag (not strictly used when autokeying only - is also used when keyframing these days) * note: AUTOKEY_FLAG_* is used with a macro, search for lines like IS_AUTOKEY_FLAG(INSERTAVAIL) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index a441f2f57dc..82afcfdbf29 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3263,7 +3263,14 @@ static void rna_def_userdef_view(BlenderRNA *brna) "Direct conversion of frame numbers to seconds"}, {0, NULL, 0, NULL, NULL} }; - + + static EnumPropertyItem zoom_frame_modes[] = { + {ZOOM_FRAME_MODE_KEEP_RANGE, "KEEP_RANGE", 0, "Keep Range", ""}, + {ZOOM_FRAME_MODE_SECONDS, "SECONDS", 0, "Seconds", ""}, + {ZOOM_FRAME_MODE_KEYFRAMES, "KEYFRAMES", 0, "Keyframes", ""}, + {0, NULL, 0, NULL, NULL} + }; + PropertyRNA *prop; StructRNA *srna; @@ -3505,6 +3512,22 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_ui_text(prop, "TimeCode Style", "Format of Time Codes displayed when not displaying timing in terms of frames"); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "view_frame_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, zoom_frame_modes); + RNA_def_property_enum_sdna(prop, NULL, "view_frame_type"); + RNA_def_property_ui_text(prop, "Zoom To Frame Type", "How zooming to frame focuses around current frame"); + + prop = RNA_def_property(srna, "view_frame_keyframes", PROP_INT, PROP_NONE); + RNA_def_property_range(prop, 1, 500); + RNA_def_property_ui_text(prop, "Zoom Keyframes", + "Keyframes around cursor that we zoom around"); + + prop = RNA_def_property(srna, "view_frame_seconds", PROP_FLOAT, PROP_TIME); + RNA_def_property_range(prop, 0.0, 10000.0); + RNA_def_property_ui_text(prop, "Zoom Seconds", + "Seconds around cursor that we zoom around"); + } static void rna_def_userdef_edit(BlenderRNA *brna) @@ -3625,7 +3648,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_ui_text(prop, "New Interpolation Type", "Interpolation mode used for first keyframe on newly added F-Curves " "(subsequent keyframes take interpolation from preceding keyframe)"); - + prop = RNA_def_property(srna, "keyframe_new_handle_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, keyframe_handle_type_items); RNA_def_property_enum_sdna(prop, NULL, "keyhandles_new"); |